# Skills Workflow Documentation — Full Text Source: https://documentation.skillsworkflow.com Generated: 2026-10-02 Pages: 392 Every page below is delimited by a `---` rule followed by its title and canonical URL. Unreviewed legacy content (/docs/to-review/) is excluded. # Integrations --- ## 7Log URL: https://documentation.skillsworkflow.com/docs/integrations/7Log Summary: 7Log is where the agency's client requests are registered and tracked commercially. ### Description This article describes the integration between **7Log** and `Skills Workflow`. 7Log is where the agency's client requests are registered and tracked commercially. Skills Workflow is where the work those requests turn into is planned, staffed and delivered. This integration connects the two, so that a request accepted in 7Log becomes a live project in Skills Workflow on its own, and stays aligned as it advances. Without it, someone reads the day's requests in 7Log and re-creates each one by hand — retyping the client, the description, the dates, the cost centre and the owner, and then remembering to move the project every time the request changes phase. That is slow, and it quietly drifts: the two systems end up disagreeing about which jobs exist and what state they are in. With it, the commercial team keeps working in 7Log, the delivery team keeps working in Skills Workflow, and neither has to maintain the other's list. --- ### Data Exchange Technology The exchange runs over the 7Log web API. Skills Workflow authenticates with a dedicated API user and then calls 7Log directly. No files, no FTP servers and no locally installed application are required. The integration is **scheduled, not event-driven**. Every 15 minutes it asks 7Log for the requests that changed in the previous hour, and processes each one. The overlapping window means a request is still picked up if a run is delayed or a single call fails. The exchange is **one-way**: 7Log is the source of truth for the request, and Skills Workflow follows it. Changing a project in Skills Workflow does not write anything back to 7Log. --- ### Data Exchange (To Skills Workflow) **Requests → Projects** Each request in 7Log corresponds to one project in Skills Workflow, matched on the request number. The following information is carried across: | Received from 7Log | Becomes in Skills Workflow | | --- | --- | | Request number | Project number — the key that links the two records | | Client code | The client the project belongs to | | Description | Project name | | Creation date | Project start date (the end date defaults to 30 days later) | | Brand | The client's product | | Intervention type | Project nature | | Phase | Project stage | | Cost centre | The project's **Centro_Custo** field | | Created by | Project owner, who is also assigned to the project | **What each phase does** The phase held in 7Log decides what happens, so that only requests that represent real work reach Skills Workflow: | Phase in 7Log | Result | | --- | --- | | Registo, Faturação, Orçamentação | The project is created, if it does not exist yet | | Concluído | Ignored — a request that is already finished does not open a project | | Any other phase | Ignored | Once a project exists, a later phase change in 7Log moves the project to the matching stage in Skills Workflow. If the project is already in that stage, nothing happens — so a request that generates several updates does not produce a string of duplicate transitions. --- ### What the Agency Needs to Provide - **A 7Log API address and a dedicated API user** for Skills Workflow to authenticate with. - **Clients registered in Skills Workflow, carrying their 7Log client code.** This is the link between the two systems — see *Good to Know* below. - **Project natures** in Skills Workflow matching the intervention types used in 7Log. - **Workflow stages** on the Project document type matching the 7Log phases, with valid transitions between them. - **A notification e-mail address** to receive the integration's alerts. --- ### Monitoring and Error Handling The integration does not guess when something does not line up. It skips the request and reports it, so the gap is visible and fixable rather than silently wrong. An e-mail is sent when: - the intervention type on the request does not match any project nature in Skills Workflow; - the project could not be created; - the request moved to a phase that Skills Workflow has no available transition to. A problem with one request does not stop the run — the remaining requests are still processed, and the skipped one is picked up on a later run once the missing mapping is in place. --- ### Good to Know - **The client has to exist in Skills Workflow first.** A request for a client that is not registered — or that is registered without its 7Log client code — is skipped. This is the most common reason a request does not appear, and it is worth checking before going live. - **Only the last hour is polled, every 15 minutes.** A request registered in 7Log appears in Skills Workflow within a few minutes, not instantly. - **Finished requests are never imported.** If a request is registered and completed in 7Log without ever being polled in between, no project is created for it. - **Projects are matched by request number**, which should not be edited by hand. - The integration is one-way: moving a project in Skills Workflow does not change the request in 7Log. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | 7Logs-Scheduler | Automation | 2 | Active | Runs every 15 minutes; enqueues `7Logs-GetJobsByPeriod` for the last hour | | 7Logs-GetJobsByPeriod | Automation | 2 | Active | Authenticates to 7Log, pulls jobs in a period, creates/updates the matching Skills Workflow project | | 7Logs-ProjectByNumber-Get | Query | 3 | Active | Decides, per job, whether to Create/Update/Ignore or flag a missing client mapping | | 7Logs-TransitionByProjectAndName-Get | Query | 1 | Active | Looks up the workflow transition needed to move a project to a given stage | Source: `[7Log] [Integrations] 7Logs-Scheduler v2 (Automation) {Active}.json`, `[7Log] [Integrations] 7Logs-GetJobsByPeriod v2 (Automation) {Active}.json`, `[7Log] [Integrations] 7Logs-ProjectByNumber-Get v3 (Query) {Active}.json`, `[7Log] [Integrations] 7Logs-TransitionByProjectAndName-Get v1 (Query) {Active}.json`. #### How It Works 1. **`7Logs-Scheduler`** runs every 15 minutes. It computes a `Start`/`End` window (now minus one hour, to now) and enqueues `7Logs-GetJobsByPeriod` (its own automation id) as background work with that window. 2. **`7Logs-GetJobsByPeriod`** authenticates against the 7Log API (`POST {host}/Token`, password grant, host read from the `7log-api` configuration key) and fetches jobs changed in the window (`POST {host}/API/Pedidos/GetJobs`, `tipoData: 1`). 3. For each job returned, it calls **`7Logs-ProjectByNumber-Get`** (`POST /api/v3/analytics/named-query/7Logs-ProjectByNumber-Get/execute`), which returns an `action`: - `Client` — the 7Log client (`codEntidade`) isn't mapped to a Skills Workflow client (matched on `commercialClient.externalId`) → the job is skipped. - `Exists` — the project already matches the incoming stage → skipped. - `Ignore` — the incoming stage isn't one Skills Workflow tracks (including `Concluído`) → skipped. - `Create` — no project exists yet: - If the query couldn't resolve a `projectNatureId`, an email is sent ("Project Nature '...' Not Found") and the job is skipped. - Otherwise `POST /api/v3/projects` creates it, `PUT /api/v3/documentUserFieldValues` sets the `Centro_Custo` custom field, and `POST /api/v3/posts` assigns the project owner (assignment type id `f00eff4d-a086-4d9c-bd9a-ee4df79fd401`). A `400/401/403/404` from the create call sends an email ("Create Project '...' Error"). - `Update` — a project exists but its stage differs: - **`7Logs-TransitionByProjectAndName-Get`** looks up the transition to the target stage. If none is available, an email is sent ("Transition Not Available For Stage '...'"); otherwise `POST /api/posts` applies the transition. 4. All error/skip emails go to `ines@skillsworkflow.com`, sent as "7Jobs | Skills Workflow". The scheduler notifies on error only, not on success. Field mapping performed inside `7Logs-ProjectByNumber-Get`: `numeroPedido` → project number, `codEntidade` → client (via `externalId`), `descricao` → name (stripped of quotes and non-breaking spaces), `dataCriacao` → begin date (end date defaults to +30 days), `marca` → `commercialClientProduct`, `tipoIntervencao` → `projectNature` (with `Faturação` mapped to the nature named `Projeto`), `fase` → workflow state, `centroCustos` → `Centro_Custo`, `criadoPor`/`atualizadoPor` (e-mails) → users, falling back to the `internal process` user. #### External System Contact Points - 7Log API (host read from the `7log-api` configuration key): - `POST {host}/Token` — OAuth2 password grant. - `POST {host}/API/Pedidos/GetJobs` — `{Start, End, tipoData: 1}`, bearer-authenticated. - Skills Workflow's own API/analytics: `POST /api/v3/projects`, `PUT /api/v3/documentUserFieldValues`, `POST /api/v3/posts`, `POST /api/posts`, named queries `7Logs-ProjectByNumber-Get` and `7Logs-TransitionByProjectAndName-Get`. #### Configuration - Configuration key **`7log-api`** — holds the 7Log API host. Credentials in this export are inline in the automation body rather than in the configuration key — see Open Questions. - Custom field **`Centro_Custo`** on Project. - Assignment type id `f00eff4d-a086-4d9c-bd9a-ee4df79fd401` — used to assign the project owner. #### Open Questions - The 7Log API password appears in plain text in the exported automation body rather than in a configuration key — whether this reflects the live system or is an export artefact is not determinable from the export. - The full set of project-nature and client-mapping rules lives inside the `7Logs-ProjectByNumber-Get` SQL and depends on data in Skills Workflow's own tables — which specific 7Log values map to which records is not enumerable from the export alone. --- ## Active Collab URL: https://documentation.skillsworkflow.com/docs/integrations/Active-Collab Summary: ActiveCollab is the day-to-day task tracker some teams live in — a board of tasks, lists, comments and attachments. ### Description This article describes the integration between **ActiveCollab** and `Skills Workflow`. ActiveCollab is the day-to-day task tracker some teams live in — a board of tasks, lists, comments and attachments. Skills Workflow is where those tasks have to exist as jobs, so they can be costed, resourced, reported on and billed. This integration mirrors one into the other continuously. The value is that neither team has to change how they work. The people executing keep their board in ActiveCollab; the agency keeps a complete, current picture of the work in Skills Workflow — including the conversation around it, not just the task title. Every comment and attachment added on the board lands on the job, so the job record is genuinely the full story rather than an empty shell someone has to go elsewhere to understand. --- ### Data Exchange Technology The exchange runs over the ActiveCollab web API, using an address and token configured by the agency. No files and no locally installed application are required. The integration is **event-driven**. ActiveCollab calls Skills Workflow whenever something happens on a task, and Skills Workflow reacts immediately — there is no scheduled run and no waiting. Because it reads the full task back from ActiveCollab rather than trusting the notification, an event that arrives late or out of order still leaves the job correct. A whole project's existing tasks can also be **imported in bulk** on demand, rather than waiting for each one to change individually. This is how a project already underway in ActiveCollab is brought into Skills Workflow. The exchange is **one-way**: ActiveCollab is the source of truth for the task, and Skills Workflow follows it. --- ### Data Exchange (To Skills Workflow) **Tasks → Jobs** | What happens in ActiveCollab | Result in Skills Workflow | | --- | --- | | A task is created | A job is created, with its brief, its initial stage, its tags and the person who raised it | | A task is renamed, re-tagged or re-assigned | The matching job is updated, and tags no longer on the task are removed from the job | | A task moves to a different task list | The job moves to the matching workflow stage | | A comment is added to a task | The comment appears on the job | | A file is attached to a task | The attachment is recorded on the job | When a job is created, the integration also pulls across the comments the task already had, so the job does not start out missing its history. --- ### What the Agency Needs to Provide - **An ActiveCollab account with API access**, plus the address and token for Skills Workflow to authenticate with. - **Webhooks configured in ActiveCollab** pointing at Skills Workflow, for task, comment and attachment events. - **A Skills Workflow project** matching each ActiveCollab project that should be mirrored, carrying its ActiveCollab identifier. - **Agreement on which task list corresponds to which workflow stage**, and which department and assignment type new jobs should be created under. --- ### Good to Know - **Jobs and tasks are matched by the ActiveCollab task identifier**, stored on the job. It should not be edited manually. - **An update only lands if the job already exists.** If a task was never imported in the first place, later changes to it have nothing to update — this is the usual reason a change does not appear, and it is fixed by running the bulk import for that project. - **Task lists have to map to real stages.** A task moved to a list with no matching Skills Workflow stage leaves the job where it is. - The integration is one-way: moving a job or editing its brief in Skills Workflow does not change the task in ActiveCollab. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | ActiveCollab-ProcessWebHook | Automation | 2 | Active | Single inbound endpoint: dispatches every ActiveCollab webhook event to the matching automation below | | ActiveCollab-CreateTask | Automation | 3 | Active | Creates a job from a new ActiveCollab task | | ActiveCollab-UpdateTask | Automation | 2 | Active | Updates a job's fields/tags from an updated ActiveCollab task | | ActiveCollab-TaskListChanged | Automation | 2 | Active | Moves a job's stage when its task changes task-list | | ActiveCollab-CommentCreated | Automation | 2 | Active | Adds a comment to a job from an ActiveCollab task comment | | ActiveCollab-AttachmentCreated | Automation | 2 | Active | Records a job comment when a file is attached in ActiveCollab | | ActiveCollab-ImportProjectTasks | Automation | 3 | Active | On-demand bulk import of a whole ActiveCollab project's tasks | | ActiveCollab-GetJobByExternalId | Query | 2 | Active | Looks up the job matching an ActiveCollab task id | | ActiveCollab-GetProjectByExternalId | Query | 1 | Active | Looks up the Skills Workflow project matching an ActiveCollab project id | | ActiveCollab-GetStageByName | Query | 2 | Active | Resolves a workflow stage by name, for task-list changes | | ActiveCollab-GetTransitionByName | Query | 2 | Active | Resolves a workflow transition by name, for job creation | | ActiveCollab-GetUserByEmail | Query | 2 | Active | Looks up a Skills Workflow user by e-mail — not called by any automation in this export | Source: `[Active Collab] [Integrations] Process WebHook v2 (Automation) {Active}.json`, `[Active Collab] [Integrations] Create Task v3 (Automation) {Active}.json`, `[Active Collab] [Integrations] Update Task v2 (Automation) {Active}.json`, `[Active Collab] [Integrations] Task List Changed v2 (Automation) {Active}.json`, `[Active Collab] [Integrations] Comment Created v2 (Automation) {Active}.json`, `[Active Collab] [Integrations] Attachment Created v2 (Automation) {Active}.json`, `[Active Collab] [Integrations] Import Project Tasks v3 (Automation) {Active}.json`, and the named queries above. #### How It Works 1. ActiveCollab calls a single Skills Workflow webhook endpoint for every event; `ActiveCollab-ProcessWebHook` reads `Body.type` and enqueues the matching automation as background work (confirmed by matching automation ids): `TaskCreated` → `ActiveCollab-CreateTask` (`5ce6bf8d-...`), `TaskUpdated` → `ActiveCollab-UpdateTask` (`0e7691b1-...`), `TaskListChanged`/`TaskListChangedFromReorder` → `ActiveCollab-TaskListChanged` (`ddd8e1a9-...`), `CommentCreated` → `ActiveCollab-CommentCreated` (`e344d852-...`), `AttachmentCreated` → `ActiveCollab-AttachmentCreated` (`109f79d5-...`). Any other type exits without action. 2. **Create**: `ActiveCollab-CreateTask` fetches the full task from ActiveCollab (`GET {host}/api/v1/projects/{id}/tasks/{id}`), resolves the Skills Workflow project (`ActiveCollab-GetProjectByExternalId`), the creating user by e-mail, department and assignment type, then creates the job (`POST /api/jobs`), sets custom fields, posts the brief (`POST /api/documentBriefs`), applies the initial transition (`ActiveCollab-GetTransitionByName`, `POST /api/posts`), pulls existing comments from ActiveCollab, and tags the job. 3. **Update**: `ActiveCollab-UpdateTask` re-fetches the task, finds the job by external id, updates the brief, patches the job (`PATCH /api/jobs/{id}`), and reconciles tags (adding new ones, deleting ones no longer present). 4. **Stage change**: `ActiveCollab-TaskListChanged` fetches the new task-list's name from ActiveCollab, resolves it to a Skills Workflow stage (`ActiveCollab-GetStageByName`), finds the job (`ActiveCollab-GetJobByExternalId`), and sets its workflow state directly (`PUT /api/jobs/{id}/workflowstate`). 5. **Comments/attachments**: `ActiveCollab-CommentCreated` and `ActiveCollab-AttachmentCreated` post the comment/attachment onto the matching job (`POST /api/v3/posts`). 6. **Bulk import**: `ActiveCollab-ImportProjectTasks`, run on demand for a project, fetches all of that project's tasks from ActiveCollab and checks each against `ActiveCollabId` custom field values already in Skills Workflow, to import only what isn't already there. #### External System Contact Points - ActiveCollab API (`{host}` from a `Config` configuration key): `GET /api/v1/projects/{id}/tasks/{id}`, `GET /api/v1/projects/{id}/tasks`, `GET /api/v1/projects/{id}/task-lists/{id}`, `GET /api/v1/users/{id}`, `GET /api/v1/comments/task/{id}`, `POST /api/v1/projects/{id}/tasks/{id}/subtasks`. - Inbound: ActiveCollab calls `ActiveCollab-ProcessWebHook`'s endpoint for every task/comment/attachment event. - Skills Workflow's own API/analytics: the named queries above; `POST /api/jobs`, `PATCH /api/jobs/{id}`, `PUT /api/jobs/{id}/workflowstate`, `POST /api/documentBriefs`, `POST /api/posts`, `POST /api/v3/document/{id}/tags`, `PUT /api/v3/documentUserFieldValues`. #### Configuration - A `Config` configuration key — holds the ActiveCollab host/token. Values are not part of the export. - Custom field **`ActiveCollabId`** on Deliverable — links a job back to its ActiveCollab task id, used for lookups and to detect already-imported tasks. - `Parameters.departmentName` and `Parameters.assignmentType` — used to resolve which department/assignment type new jobs get; their values are not part of the export. #### Open Questions - `ActiveCollab-GetUserByEmail` isn't called by any exported automation — the other flows call `GET /api/users/email?email=` directly instead, so whether this query is used elsewhere isn't determinable. - How ActiveCollab is configured to send its webhooks to `ActiveCollab-ProcessWebHook` (which events, which projects) is not part of this export. --- ## AdnNet URL: https://documentation.skillsworkflow.com/docs/integrations/adnet Summary: AdnNet is the agency's administrative and financial back office. ### Description This article describes the integration between **AdnNet** and `Skills Workflow`. AdnNet is the agency's administrative and financial back office. The integration keeps the two systems aligned so that the commercial teams work in Skills Workflow and the finance teams keep working in AdnNet, without anyone having to retype the same client, supplier, job or invoice twice. In practice, the integration takes care of two jobs: - **Bringing the master data in** — clients and suppliers that already exist in AdnNet are created and kept up to date in Skills Workflow. - **Sending the operation out** — jobs, bills and supplier invoices approved in Skills Workflow are pushed into AdnNet so that finance can invoice and pay from them. --- ### Data Exchange Technology The exchange runs over the AdnNet web API. Skills Workflow authenticates with a login and an API key configured by the agency, and then calls AdnNet directly. No files, no FTP servers and no locally installed application are required. The integration runs on a schedule, company by company. Each company configured on the agency's tenant is processed independently, with its own AdnNet credentials and its own settings. On the very first run for a company, the integration pulls the last month of client and supplier data from AdnNet. From then on it only picks up what changed since the previous successful run. --- ### Data Exchange (To Skills Workflow) The following records are received from AdnNet: **Clients** Clients registered in AdnNet are created and updated in Skills Workflow as: - Billing Clients - Commercial Clients — only when the **Create Commercial Client** setting is enabled - The link between a Commercial Client and the company it belongs to Client records include the legal and trading names, tax identification, addresses (both the main address and the billing address), city, state, postal code, country, e-mail and the active/inactive status held in AdnNet. Cities and countries are matched against the ones already registered in Skills Workflow. **Suppliers** Suppliers registered in AdnNet are created and updated in Skills Workflow as Suppliers, with the same identification and address information. Records already imported keep their AdnNet identifier, so subsequent runs update the existing record instead of creating a duplicate. --- ### Data Exchange (From Skills Workflow) The following documents are sent to AdnNet: **Projects → Jobs** Projects created in Skills Workflow are opened as jobs in AdnNet. The job number returned by AdnNet is written back onto the project in Skills Workflow, so both systems share the same reference. **Bills → Invoice orders** Bills issued in Skills Workflow are sent to AdnNet as invoice orders, against the job created in the previous step. Only bills of the document type configured in **Bill Document Type** are exported. **Supplier Invoices → Checkings** Supplier invoices registered in Skills Workflow are sent to AdnNet. Only supplier invoices of the document type configured in **Supplier Invoice Document Type** are exported. Each document that is successfully exported is marked as synchronised, so it is not sent again on the next run. --- ### Settings the Agency Controls The integration is configured per company, from the integration settings area in Skills Workflow: | Setting | What it does | | --- | --- | | Url | Address of the agency's AdnNet API | | Login | User the integration authenticates with in AdnNet | | Api Key | Key used together with the login | | Create Commercial Client | Whether clients imported from AdnNet should also be created as Commercial Clients | | Bill Document Type | Which Skills Workflow document type is treated as a bill for export | | Supplier Invoice Document Type | Which Skills Workflow document type is treated as a supplier invoice for export | | Administrator Mail | Address that receives the error notifications for this company | | Log Level Type | How much detail is written to the integration log | --- ### What the Agency Needs to Provide - A reachable AdnNet API address, plus a dedicated login and API key for Skills Workflow. - Confirmation of which document types in Skills Workflow correspond to bills and to supplier invoices. - An administrator e-mail address to receive integration notifications. --- ### Monitoring and Error Handling Every run writes to the integration log inside Skills Workflow, at the level of detail chosen in **Log Level Type**. The log is cleared at the start of each run, so it always reflects the most recent execution. If anything fails — a record that could not be created, a document AdnNet rejected, or a connectivity problem — a summary e-mail is sent to the address configured in **Administrator Mail**. A failure on one record does not stop the rest of the run: the integration continues and reports everything that went wrong at the end. --- ### Good to Know - Records are matched by their AdnNet identifier, which is stored on the Skills Workflow record. Changing that identifier manually will cause duplicates. - Documents are only exported once. If a document needs to be re-sent, the synchronisation mark has to be cleared first. - Each company runs with its own credentials and its own settings, so different companies on the same tenant can point at different AdnNet environments. --- ## ADP URL: https://documentation.skillsworkflow.com/docs/integrations/adp Summary: This is the Documentation of how the Integration between the ADP and Skills Workflow. ### Description This is the Documentation of how the Integration between the ADP and `Skills Workflow`. --- ### Data Exchange Technology ADP places files in an FTP Server that contain infformation on employee. The files are encrypted using a PGP certificate. --- ### Data Exchange (To Skills Workflow) This section describes the Data exchanged between systems. Please see the data exchanged. The data is exchanged with Views available in the system. **The following Employee fields can be mapped:** `Employees` are received by Skills Workflow. New Employees created in ADP are automatically created in Skills Workflow as Users and Employees. When an Employee is modified in ADP, the fields affected are: - IsActive - Termination Date Employees Data Exchanged The import files contains the following fields (separated by "|"): - Matr - Nome - Empresa - CR - CRNome - Funcao - Chefia - VinculoEmpregaticio - Nascto - EMail - Telefone - Contribuinte - Pais - Naturalidade - Admissao - Demissao The fields that are populated into Users: - Name - Generated based on the "Email" (initial part, before the "@"), replacing "." for spaces and appling proper casing - UserName - Generated based on the "Email" - User Type - Is set to "VinculoEmpregaticio" - Company - Derived from "Empresa" - External ID - Set to "Matr" - Department - Taken from "CR" - Typology - Mapped using Department and "Funcao" - E-mail - Set to "Email" - Hire Date - Set to "Admissao" - IsActive - Derived from "Demissao" when not empty - SSO Username - Responsible - The User set in "Chefia" - Tax Payer Number - Set to "Contribuinte" The fields that are populated into Employees: - Name - Set to "Nome" - Company - Derived from "Empresa" - External ID - Set to "Matr" - IsActive - Derived from "Demissao" when not empty The following entities are created if they do not exist: - Department - Typologies - User Types Terminated employees will be automatically inactivated in Skills Workflow. SSO Username will be populated with e-mail coming from ADP. --- ### Conclusion The contents of this document create the foundation for data and process communication methodology between Skills Workflow and Customers. The current known data and process transfers are contained in this document but more may be created as additional data and process needs are discovered. --- ## AdSolutions URL: https://documentation.skillsworkflow.com/docs/integrations/AdSolutions Summary: AdIntegra is the agency's ad and media management back office — where campaigns and the individual pieces that make them up are registered for media planning… Despite the similar-sounding name, this integration is unrelated to the [AdnNet](adnet) integration already documented on this site — the two connect to different external systems (this one to "AdIntegra", a SOAP/ASMX web service, per every exported component's `AdIntegraSkillsWS-` prefix and `AdIntegraSkills.asmx` endpoint). ### Description This article describes the integration between **AdIntegra** (the AdSolutions platform) and `Skills Workflow`. AdIntegra is the agency's ad and media management back office — where campaigns and the individual pieces that make them up are registered for media planning and billing. Skills Workflow is where that work is briefed, produced and tracked. The integration takes care of two jobs: - **Bringing the master data in** — clients, billing products, suppliers and services that already exist in AdIntegra are created and kept up to date in Skills Workflow, so briefs are raised against the same records media and finance use. - **Sending the operation out** — as soon as a project or job is real (it has left draft), it is registered in AdIntegra as a campaign or an ad piece, and the reference AdIntegra assigns is written back onto the Skills Workflow record. The point is that a job only has to be described once. The producer briefs it in Skills Workflow; media and finance find it already waiting in AdIntegra under the right client and campaign, carrying a shared reference both sides can quote. --- ### Data Exchange Technology The exchange runs over the AdIntegra web service, using a login and password configured by the agency. Skills Workflow authenticates for a token and then calls AdIntegra directly. No files and no locally installed application are required. It works in two modes: - **The outbound hand-off is event-driven** — it fires the moment a project or job leaves the draft stage. - **The inbound master-data refresh is a batch pull**, run per company and per date range. As exported, the automation that drives the periodic clients/suppliers/services refresh has its schedule switched off, so that half does not run on its own. The outbound job and project hand-off is unaffected and remains live. See the Technical Reference for detail. --- ### Data Exchange (To Skills Workflow) Pulled from AdIntegra, per company: - **Clients** — created as billing clients and commercial clients, with the link to the company they belong to. - **Billing products** — created as billing and commercial products. - **Suppliers**. - **Services**. --- ### Data Exchange (From Skills Workflow) | Sent to AdIntegra | When | | --- | --- | | **Projects → Campanhas** (campaigns) | The project leaves the *Rascunho* (draft) stage | | **Jobs → Peças** (ad pieces) | The job leaves the *Rascunho* (draft) stage | In both cases the reference AdIntegra returns is stored back on the Skills Workflow record, so the two systems share the same identifier from then on. --- ### What the Agency Needs to Provide - **An AdIntegra web service address**, plus a dedicated login and password for Skills Workflow. - **The departments in scope** for the integration, and the stage name that means a client is confirmed — both held in the integration's system parameters. - **A *Rascunho* (draft) stage** on the Project and Job document types, since leaving it is what triggers the hand-off. --- ### Good to Know - **Nothing is sent while a project or job is still in draft.** This is deliberate: it keeps half-written briefs out of the media system. - **Records are matched by their AdIntegra reference**, stored on the Skills Workflow record. - Master data flows in, operational documents flow out — the two directions are independent, and one can be running while the other is not. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | AdIntegraSkillsWS-ScheduleTask | Automation | 2 (highest of 2 versions, both exported) | **No active trigger** | Would enqueue the Clients/Suppliers/Services refresh — both exported versions have their scheduler disabled | | AdIntegraSkillsWS-Authenticate | Automation | 1 | Active | Shared helper: gets an AdIntegra API token | | AdIntegraSkillsWS-BillingClients | Automation | 2 (highest of 2 versions, both exported) | Active | Pulls clients from AdIntegra for a date range | | AdIntegraSkillsWS-BillingProducts | Automation | 1 | Active | Pulls billing products from AdIntegra | | AdIntegraSkillsWS-Services | Automation | 1 | Active | Pulls services from AdIntegra | | AdIntegraSkillsWS-Suppliers | Automation | 2 | Active | Pulls suppliers from AdIntegra | | AdIntegraSkillsWS-Job-CreatePeca | Automation | 5 (highest of 2 versions, both exported) | Active | Sends a job to AdIntegra as a "Peça" | | AdIntegraSkillsWS-Job-Created | Webhook | 1 | Active | Fires `Job-CreatePeca` when a Deliverable leaves the "Rascunho" stage | | AdIntegraSkillsWS-Project-CreateCampanha | Automation | 4 | Active | Sends a project to AdIntegra as a "Campanha" | | AdIntegraSkillsWS-Project-Created | Webhook | 1 | Active | Fires `Project-CreateCampanha` when a Project leaves the "Rascunho" stage | | AdIntegraSkillsWS-Parameters | System Parameter | 2 | Active | Holds AdIntegra login (`usuario`, `senha`), the departments in scope, and the "client is clear" stage name | | AdIntegraSkillsWS-BillingClient-Get, -BillingProduct-Get, -Client-Get, -ClientesCompany-Filter, -CompaniesAndDates-Get, -Product-Get, -Service-Get, -Supplier-Get, -Job-Get, -Project-Get | Query | various | Active | Resolve/build the payloads for the automations above | Source: files under `[AdSolutions] [Integrations] AdIntegraSkillsWS-...` in the Marketplace export (26 files, 22 distinct components after de-duplicating attachments and version history). `AdIntegraSkillsWS-ScheduleTask` is exported in two versions (v1 and v2) and **both have their scheduler `isActive: false`**. Its job is to enqueue `AdIntegraSkillsWS-BillingClients`, `-Suppliers` and `-Services` (confirmed by matching target automation ids) — with no active scheduler calling it, none of those three master-data pulls currently run on their own. Only the job/project webhook-triggered push to AdIntegra remains live. #### How It Works **Periodic master data** (currently untriggered — see above): `AdIntegraSkillsWS-ScheduleTask` would authenticate (`AdIntegraSkillsWS-Authenticate`, `POST {host}/AdIntegraSkills.asmx/TOKEN`) and then, for each company/date range from `AdIntegraSkillsWS-CompaniesAndDates-Get`, enqueue `AdIntegraSkillsWS-BillingClients`, `-Suppliers` and `-Services` as background work. Each of those pulls the relevant AdIntegra endpoint (`POST {host}/AdIntegraSkills.asmx/CLIENTES` / `FORNECEDORES` / `PRODUTOS`), parses the XML response, resolves each record against Skills Workflow (`AdIntegraSkillsWS-BillingClient-Get` etc.), and creates/updates it. `AdIntegraSkillsWS-BillingProducts` follows the same pattern but isn't wired into the scheduler at all in this export. **Job/Project hand-off** (active, webhook-triggered): when a Deliverable or Project transitions out of "Rascunho", the matching webhook fires `Job-CreatePeca` or `Project-CreateCampanha` (confirmed by matching automation ids). Each authenticates, runs its own `-Get` query (`AdIntegraSkillsWS-Job-Get` / `-Project-Get`) to build the AdIntegra payload, sends it (`POST {host}/AdIntegraSkills.asmx/PECAS` / `CAMPANHAS`), and writes the returned external reference back (`PUT /api/v3/documentUserFieldValues` for jobs, `PATCH /api/v3/project-companies/{id}` for projects). #### External System Contact Points - AdIntegra SOAP/ASMX service (`{host}/AdIntegraSkills.asmx`, host passed per-request rather than fixed): `/TOKEN`, `/CLIENTES`, `/PRODUTOS`, `/FORNECEDORES`, `/PECAS`, `/CAMPANHAS`. - Skills Workflow's own API/analytics: the named queries above; `POST /api/v3/billing-clients`, `POST /api/v3/commercial-clients`, `POST /api/v3/commercial-client-companies`, `POST /api/v3/billing-products`, `POST /api/v3/commercial-products`, `POST /api/v3/commercial-product-companies`, `POST /api/v3/services`, `POST /api/v3/suppliers`, `PUT /api/v3/documentUserFieldValues`, `PATCH /api/v3/project-companies/{id}`. #### Configuration - System Parameter **`AdIntegraSkillsWS-Parameters`** — `usuario`, `senha` (AdIntegra login), `departamentos` (departments in scope), `etapaClienteClaro` (the stage name meaning "client is clear/confirmed"). Values are redacted in the export. #### Open Questions - Whether the master-data sync being untriggered is intentional (e.g. run manually, or superseded by something else) is not determinable from the export. - `AdIntegraSkillsWS-BillingProducts` isn't enqueued by `AdIntegraSkillsWS-ScheduleTask` even if that scheduler were re-enabled — what's meant to trigger it isn't determinable. --- ## API URL: https://documentation.skillsworkflow.com/docs/integrations/api Summary: Every other integration in this section is, underneath, this API being used. ## Description This article describes the **Skills Workflow API**. Every other integration in this section is, underneath, this API being used. It is the interface any external system uses to read and write Skills Workflow data directly — clients, suppliers, users, jobs, projects, estimates, expenses, files and more — without a person entering it by hand. It exists for the cases the packaged integrations do not cover. When an agency runs a system nobody has built a connector for, or wants to automate something specific to how they work, the API is what makes that possible without waiting for a product change. It is also how an implementation partner loads data during onboarding, and how a client's own systems can be wired into the platform. Two collections are published: - **Integration API** — the endpoints for provisioning and maintaining master data, such as users and employees. - **Client API** — the broader day-to-day object model: jobs, projects, contracts, requests, estimates, expenses, assignments, comments, files and workflow. The API is versioned and additive: it keeps growing, but without breaking what already works — so an integration built against it does not need revisiting every release. --- ## Authentication API URLs: - API: https://integration-api-we.skillsworkflow.com/ - Docs: https://integration-api-we.skillsworkflow.com/swagger/ui/index You can try the API directly from the documentation, or you can use other application (e.g. PostMan) To use the API you will need to send 3 Headers in the request, as required in the documentation: X-AppTenant, X-AppId and X-AppSecret You can also check our open source site and check some examples of using the API: https://github.com/SkillsWorkflow/api-demos If you need to, please request the test (UAT) environment credentials for your Agency: - X-AppTenant - X-AppId - X-AppSecret Example on how to get all companies: The API is constantly evolving (but never having breaking changes): - If you need something that you do not find in the API, do not hesitate to ask and we will analyze the feasibility of adding to the API ## Billing Client ### Adding new billing client To add a new Billing Client, you must specify the following properties: - ExternalId - CompanyCode - Name The External Id should match the unique identifier of the Billing Client in the external system. If the client already exists, it will be updated using the External Id and Company Code as the key. ``` json Method: POST Endpoint: /api/billingclients Payload: { "name": "string", "companyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "companyCode": "string", "externalId": "string", "code": "string", "number": "string", "street": "string", "street2": "string", "stateProvince": "string", "city": "string", "cityId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "zipPostal": "string", "country": "string", "countryId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "active": true, "taxpayerNumber": "string", "paymentConditionExternalId": "string", "setFirstPaymentConditionIfExternalIdIsNull": true, "applyDefaultPaymentCondition": true, "currencyExternalId": "string", "applyDefaultCurrency": true, "otherDebtor": true } ``` ## Commercial Client ### Adding new commercial client A Commercial Client should be created after all Billing Clients for a given company have been created. To create a Commercial Client, you must specify the following properties - Name - ExternalId. The External Id used for the Commercial Client should match the unique identifier of the Billing Client in the external system (the same External Id used when creating the Billing Client). ``` json Method: POST Endpoint: /api/commercialclients Payload: { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "externalId": "string", "nameAndExternalId": "string", "code": "string", "number": "string", "street": "string", "street2": "string", "stateProvince": "string", "blocked": true, "taxpayerNumber": "string", "country": "string", "countryId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "zipPostal": "string", "city": "string", "cityId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "commercialPaymentConditionExternalId": "string", "clientGroupExternalId": "string", "projectOwnerExternalId": "string", "setFirstPaymentConditionIfExternalIdIsNull": true, "applyDefaultPaymentCondition": true, "companyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "timesheetLevelId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "insertUpdateCheckOnlyId": true, "_options": { "ignoreCode": true, "linkDefaultCompany": true } } ``` ### Associate with billing client To associate a commercial client with a billing client, you must indicate the id of the commercial client creation response, the id and the companyId of the billing client creation response, so as to be unique per company. ``` json Method: POST Endpoint: /api/commercial-client-companies Payload: { "companyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "commercialClientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "billingClientId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "externalId": "string", "vatExternalId": "string" } ``` ## Supplier ### Adding new supplier To create a supplier, you must specify the follwing properties: - ExternalId - CompanyCode - Name The externalId should match the unique identifier of the supplier in the external system. If the supplier already exists, it will be updated using the externalId and companyCode as the key. ``` json Method: POST Endpoint: /api/suppliers Payload: { "name": "string", "externalId": "string", "companyId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "companyCode": "string", "taxpayerNumber": "string", "active": true, "street": "string", "street2": "string", "countryId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "city": "string", "cityId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "zipPostal": "string", "stateProvince": "string", "otherCreditor": true, "paymentConditionExternalId": "string", "applyDefaultPaymentCondition": true, "currencyExternalId": "string", "applyDefaultCurrency": true, "vatExternalId": "string", "applyDefaultVat": true, "_options": { "disableVatUpdate": true } } ``` --- ## Marketplace Export Reference Two Postman collections are published in the Marketplace under `API`: `Client API` (v15) and `Integration API` (v2). Source: `[API] [Integrations] Client API v15 (Postman) {Active}.json`, `[API] [Integrations] Integration API v2 (Postman) {Active}.json`. ### Integration API (v2) As exported, this collection has three requests — narrower than the Billing/Commercial Client and Supplier endpoints documented above, which are not part of this particular export (not determinable whether they've moved elsewhere or simply weren't included when this collection was exported): | Request | Method & Endpoint | Notes | | --- | --- | --- | | User | `PATCH /api/users/{id}` | Partial update; only send fields you want changed | | User | `POST /api/users` | Create-or-update — send `Id` or `ExternalId` to decide which; `UserName`, `Name`, `ExternalId`, `CompanyCode`, `DepartmentExternalId`, `TypologyExternalId`, `IsActive` are required | | Employee | `POST /api/employees` | Create-or-update — send `Id` or `ExternalId`; `Name`, `ExternalId`, `CompanyId` required | Host: `https://integration-api-{Environment}.skillsworkflow.com`. ### Client API (v15) A much larger collection covering the day-to-day object model (host `https://apiv2-{Tenant}.skillsworkflow.com`, one request per folder shown; some environment-specific examples use a fixed tenant such as `chronicle`): | Area | Endpoints | | --- | --- | | Additional Information | `PUT /api/v3/documentUserFieldValues` | | Assignments | `POST /api/assignments/batch` | | Comment | `POST /api/posts` (comment), `POST /api/posts` (link file) | | Commercial Client | `POST /api/v3/commercial-clients` | | Description | `POST /api/documentBriefs` | | Estimate | `POST /api/v3/estimates`, `PUT /api/estimates/{id}/items`, `POST /api/estimates/details/thirdparty`, `POST /api/estimates/details/resources`, `POST /api/estimates/details/expenses`, `POST /api/billing-conditions` | | Expense / Expense Sheet | `POST /api/expenses`, `POST /api/expenses/{ExpenseSheetId}/items` | | File | `POST /api/v3/file-system/folders/{folderId}/links` | | Job | `PATCH /api/jobs/{jobId}`, `POST /api/v3/jobs` | | Project | `PATCH /api/projects/{id}` (and additional-information variant), `GET /api/contracts/{id}/projects/new`, `POST /api/posts` | | Contract | `PATCH /api/contracts/{id}` (and additional-information variant), `POST /api/posts` | | Typology | `POST /api/v3/user-typology-histories`, `PATCH /api/v3/user-typology-histories/{id}` | | Request | `POST /api/v3/requests`, `GET /api/v3/requests/{id}` | | User | `POST /api/v3/users` (create/duplicate), `PATCH /api/users/{id}`, `POST /api/v3/commercial-client-users` | | Workflow | `GET /api/v3/document-types/{id}/workflows?expandTransitions=true` | ### Open Questions - The Integration API export (v2) has far fewer endpoints than this page already documented (Billing Client, Supplier, Commercial Client association) — not determinable from the export whether those moved to a different collection, a different version, or are simply outdated; they're left in place above since nothing here contradicts them. --- ## Azure AD Blocker URL: https://documentation.skillsworkflow.com/docs/integrations/azure-ad-blocker Summary: Unrecorded time is one of the hardest things for an agency to fix. ### Description This article describes the **Azure AD Blocker** integration between **Microsoft Entra ID** (Azure AD) and `Skills Workflow`. Unrecorded time is one of the hardest things for an agency to fix. Timesheets are everyone's lowest priority, reminders get ignored, and by the time the gap is visible in a report it is weeks old — and with it, the ability to bill accurately, measure utilisation or trust a project's cost. This integration gives that problem consequences. Anyone required to complete timesheets who falls behind has their **Microsoft 365 sign-in disabled**, and gets it back by submitting an unblock request once they are up to date. It is a deliberately blunt instrument, and it works because it makes recording time the path of least resistance rather than the thing that can always wait until tomorrow. Both halves are automatic: the blocking, and the restoring. --- ### How It Works **Blocking** Skills Workflow identifies active users who are required to complete timesheets and are behind, and disables the matching Microsoft account. The user is then marked in Skills Workflow as blocked, so the state is visible in both systems. **Unblocking** The user (or their manager) raises an **unblock request** in Skills Workflow. Creating that request is the trigger — no administrator has to action it — and the Microsoft account is re-enabled automatically. --- ### What the Agency Needs to Provide - **An app registration in Microsoft Entra ID**, with the permissions and client secret described below, so Skills Workflow can enable and disable accounts. - **Agreement on who is in scope** — the integration only ever considers users flagged as required to complete timesheets. - **A process for unblock requests**, since raising one is what restores access. --- ### Good to Know - **Only users required to complete timesheets are ever affected.** Anyone without that requirement is out of scope entirely. - **Blocking disables the Microsoft account, not the Skills Workflow account** — it removes access to mail and everything else behind the corporate sign-in, which is what gives it its effect. - **The unblock is immediate and self-service.** Raising the request re-enables the account; nobody has to wait for IT. - The connection depends on the Entra ID client secret below, which expires. If blocking or unblocking silently stops working, that credential is the first thing to check. --- ## Azure Portal Configuration Using Microsoft Entra ID it is necessary to create a app registration to enable Integration authentication with AD allowing to update users: ### Create New App Registration - Navigate to **App Registration** - Press **New Registration** - Set name as Shown Below - Press **Register** ### Api Permissions for Graph Api - Navigate to **Api permissions** - Add the following permission for Graph Api: - User.ManageIdentities.All - User.ReadWrite.All - Grant admin consent for "Tenant Name" > Note that all the permissions should have a green **Status**. ### Client Secret - Navigate to **Certificates & secrets** - Navigate to **Client Secrets** tab - Add new Client Secret with the greatest expiration date > Copy right after creation the value key as it only shows one time ### Definitions The creation of the App Registration should have a combination of the following: - TenantId - ClientId - Client Secret (created on step above) --- ## Installation To Install the Azure AD Blocker integration please go to the Marketplace and install the Azure AD Blocker Package ### Package Content The exported package (Marketplace source files below) consists of: | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Office365 - Block Missing TimeSheets | Automation | 0 | Active | Scans for delinquent users and disables their Azure AD account | | Office365 - Unblock Missing Timesheets | Automation | 0 | Active | Re-enables an Azure AD account when an unblock request is created | | Get Delinquent Users | Query | 1 | Active | Lists users required to fill timesheets, active, with a valid AD username | | Office365-ShouldBlockUser-Get | Query | 1 | Active | Checks whether a single username still needs to be blocked | | Office365 - UnblockUserRequest | Webhook | 1 | Active | Fires the unblock automation when an `UnblockUserRequest` is created | | Office365 - UnblockUserRequest.Create | Webhook | (unversioned) | Active | A second webhook pointed directly at the same automation's execute URL, on a `playground-dev` tenant — looks like a leftover test/duplicate rather than the production trigger | Source: `[Azure AD Blocker] [Integrations] Block Missing Time Sheets v0 (Automation) {Active}.json`, `[Azure AD Blocker] [Integrations] Unblock Missing Timesheets v0 (Automation) {Active}.json`, `[Azure AD Blocker] [Integrations] Get Delinquent Users v1 (Query) {Active}.json`, `[Azure AD Blocker] [Integrations] Office365-ShouldBlockUser-Get v1 (Query) {Active}.json`, `[Azure AD Blocker] [Integrations] Unblock User Request v1 (Webhook) {Active}.json`, `[Azure AD Blocker] [Integrations] Unblock User Request Create v1 (Webhook) {Active}.json`. This is one more Query and one more Webhook than the "2 Automations, 1 Query, 1 Webhook" previously documented here — kept above rather than removed, since nothing in the export contradicts the original count, it's just incomplete. ### How It Works 1. **Blocking** (`Office365 - Block Missing TimeSheets`, triggered on demand via an HTTP request carrying a `TenantName` — no scheduler is present in this export, so what actually invokes it on a cadence isn't shown): authenticates to Azure AD, calls Skills Workflow's own analytics endpoint to run `GetDelinquentUsers` (users who must fill timesheets, are active, and have a valid AD username), then for each one disables the Azure AD account (`PATCH https://graph.microsoft.com/beta/users/{AdUserName}`, `accountEnabled: false`) and, on success, patches the user's own "is blocked in AD" flag back in Skills Workflow. 2. **Unblocking**: the `Office365 - UnblockUserRequest` webhook fires `Office365 - Unblock Missing Timesheets` (confirmed by matching automation id `e9c93597-a950-4176-8ae5-00e5e95b0d34`) whenever an `UnblockUserRequest` document is created. The automation re-enables the corresponding Azure AD account (`PATCH https://graph.microsoft.com/beta/users/{userName}`, `accountEnabled: true`). ### Configuration In both Automations is necessary to set the Azure AD parameters obtained in the **AzureAdAuthentication** Action: - tenantId - clientId - clientSecret The exported `Block Missing Time Sheets` and `Unblock Missing Timesheets` automations embed a live-looking `tenantId`/`clientId`/`clientSecret` directly in the `AzureAdAuthentication` action, rather than reading them from a configuration key — and the two Webhook files embed their own shared `secret` values in plain text. None of these values are reproduced here. If this export is genuine, treat the Azure AD app credential and both webhook secrets as compromised and rotate them. ### Open Questions - No scheduler is present on `Block Missing Time Sheets` in this export, so what actually triggers the periodic scan (and how often) isn't determinable — only that it expects an HTTP request with a `TenantName` query parameter. - `Office365 - UnblockUserRequest.Create` targets a `playground-dev` tenant URL and has no `automationId` — whether it's still live or a leftover test artifact is not determinable from the export. --- ## Azure DevOps URL: https://documentation.skillsworkflow.com/docs/integrations/Azure-DevOps Summary: Azure DevOps (Boards) is where the development team tracks its work items. ### Description This article describes the integration between **Azure DevOps** and `Skills Workflow`. Azure DevOps (Boards) is where the development team tracks its work items. Skills Workflow is where the ticket was raised, prioritised and approved. This integration keeps the two in step, so a ticket does not have to be logged twice and the two records do not drift apart. The gap it closes is a familiar one: a bug is reported and approved in Skills Workflow, then someone re-types it into Azure DevOps and, from that point on, the two systems have separate lives. The developer closes the work item; the requester still sees the ticket sitting open. This integration means the work item is created from the ticket, carries the brief's attachment with it, and follows the ticket's stage automatically — with the change attributed to whoever actually moved it, not to a service account. --- ### Data Exchange Technology The exchange runs over the Azure DevOps REST API, authenticated with an access token held in Skills Workflow's configuration. No files and no locally installed application are required. It is **event-driven** and runs in one direction: Skills Workflow is the source of truth for the ticket, and Azure DevOps follows it. Nothing done on the board writes back to Skills Workflow. --- ### Data Exchange (From Skills Workflow) **Tickets → Bug work items** A work item is created for a qualifying ticket, in the team's current iteration, with the file attached to the ticket's brief uploaded to it. Not every ticket qualifies. A ticket is skipped — deliberately, and without creating anything — when it is a customization, when it already has a work item, or when it is not marked as found in a build. **Stage changes → work item status** As the ticket advances, the work item's state is updated to match: | Ticket moves to | Azure DevOps state | | --- | --- | | Approved by PM | Approved by PM | | PM Tests | PM Validation(Dev) | | To Install | Done | The update is recorded against the e-mail address of the person who moved the ticket, so the board shows who actually made the change. Any other stage change is ignored, so unrelated movement in Skills Workflow does not create noise on the board. --- ### What the Agency Needs to Provide - **An Azure DevOps organisation, project and team**, and an access token with permission to create and update work items and upload attachments. - **The three workflow stages** above on the ticket document type, named so they can be matched. - **User e-mail addresses that match** between Skills Workflow and Azure DevOps, so the status change can be attributed correctly. --- ### Good to Know - **Only the three stages above move the work item.** If those stages are renamed, the mapping has to be updated to match. - **A ticket only ever creates one work item** — the integration checks first, so re-triggering does not produce duplicates. - **Customizations are excluded by design**, as are tickets not found in a build. - The integration is one-way. Closing a work item in Azure DevOps does not move the ticket in Skills Workflow. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Azure DevOps - Create Work Item in Visual Studio | Automation | 2 | Active | Creates a Bug work item in Azure DevOps for a qualifying deliverable, with its brief file attached | | Azure DevOps - Update work item stage | Automation | 1 | Active | Updates the Azure DevOps work item's `System.State` when the Skills Workflow deliverable's stage changes | | Azure DevOps - Update work item stage based on Ticket stage | Webhook | 1 | Active | Fires "Update work item stage" whenever a deliverable's stage changes to To Install, Approved by PM, or PM Tests | Source: `[Azure DevOps] [Integrations] Create Work Item in Azure DevOps v2 (Automation) {Active}.json`, `[Azure DevOps] [Integrations] Update work item stage v1 (Automation) {Active}.json`, `[Azure DevOps] [Integrations] Update work item stage based on Ticket stage v1 (Webhook) {Active}.json`. #### How It Works **Creating a work item** (`Create Work Item in Azure DevOps`, triggered on demand by an inbound request carrying `event.documentId.id` — the export doesn't include the webhook/button that fires it): 1. `POST /api/analytics/globalQuery/GetJobWorkItemAndBriefById/execute` looks up the deliverable/brief by id and checks flags `IsCustomization`, `HasWorkItem` and `HasFoundInBuild`. If it's a customization, already has a work item, or wasn't found in the build, the automation exits without creating anything. 2. Otherwise it reads the `AzureDevOps` configuration key for the auth token, gets the team's current iteration (`GET .../Skill Team/_apis/work/teamsettings/iterations`), and creates the work item (`POST .../_apis/wit/workitems/$Bug`). 3. It downloads the brief's file from Skills Workflow (`GET /api/v3/file-system/files/{id}/content`, then the returned download link) and attaches it to the new work item (`POST .../_apis/wit/attachments`, then `PATCH .../_apis/wit/workitems/{id}` to link the attachment) and writes the result back to the deliverable (`POST /api/posts`). **Syncing status** (`Update work item stage based on Ticket stage` webhook → `Update work item stage` automation, confirmed by matching automation id `4369ef13-ade2-4bb1-a60f-8909a0b1a0fe`): 1. The webhook listens for `StageUpdated` events on `Skill.Module.BusinessObjects.Deliverable` where the transition name is "To Install", "Approved by PM" or "PM Tests". 2. The automation looks up the work item and the user's email (`POST /api/analytics/globalQuery/execute?queryName=WorkItemUserMail`), maps the transition name to an Azure DevOps state (`To Install`→`Done`, `PM Tests`→`PM Validation(Dev)`, `Approved by PM`→`Approved by PM`), and enqueues a background patch of the work item's `System.State` and `System.ChangedBy` fields (target workflow id `7d5b3107-0afb-4f2f-87c0-aa746dd3f77c`, not part of this export). #### External System Contact Points - Azure DevOps REST API v6.0, organization `nextway`, project `Skill`, team `Skill Team` (`dev.azure.com/nextway/Skill/...`): - `GET .../Skill Team/_apis/work/teamsettings/iterations` - `POST .../_apis/wit/workitems/$Bug` - `PATCH .../_apis/wit/workitems/{id}` - `POST .../_apis/wit/attachments` - Auth: bearer/PAT token read from the `AzureDevOps` configuration key. - Skills Workflow's own API/analytics endpoints: `GetJobWorkItemAndBriefById`, `WorkItemUserMail` global queries, `/api/v3/file-system/files/{id}/content`, `/api/posts`. #### Configuration - Configuration key **`AzureDevOps`** — holds the Azure DevOps access token. Its content is not part of the export. - Two Skills Workflow global (analytics) queries, `GetJobWorkItemAndBriefById` and `WorkItemUserMail`, are referenced by name but not included in this export — their exact logic (how "customization" and "found in build" are determined) is not determinable. #### Open Questions - What triggers `Create Work Item in Azure DevOps` (a webhook, a panel button, or another automation) is not included in this export. - The background target workflow `7d5b3107-0afb-4f2f-87c0-aa746dd3f77c` that actually performs the Azure DevOps state patch is not part of this export. --- ## BambooHR URL: https://documentation.skillsworkflow.com/docs/integrations/bamboo Summary: BambooHR is where the agency's people and their time off are managed. This page previously described the integration as event-driven, firing off a BambooHR webhook. The exported components (Module `BambooHR`) show three independently **scheduled, daily-polling** automations instead — each calling BambooHR's `/v1/employees/changed?since=...&type=...` endpoint for what changed since yesterday. No webhook file exists anywhere in this export. The "Data Exchange Technology" section below has been corrected accordingly. More importantly: of the three, **only `BambooHR - Daily Employee Update` has its scheduler switched on** (`isActive: true`). `BambooHR - Daily Create Employee` and `BambooHr - Leaves Update` are both exported with `isActive: false` on their scheduler — meaning, as exported, new employees are not being created automatically and leave is not being synced, only changes to existing users' fields are. If that's not the intended current state, it needs fixing in the platform, not in this page. ### Description This article describes the integration between **BambooHR** and `Skills Workflow`. BambooHR is where the agency's people and their time off are managed. This integration keeps Skills Workflow aligned with it on two fronts: - **People** — employees created in BambooHR become users in Skills Workflow. - **Time off** — leave requested and approved in BambooHR appears as leave in Skills Workflow. The second one is what makes the difference day to day. Resourcing, scheduling, FTE and timesheets all depend on knowing who is actually available; if leave only lives in BambooHR, every one of those views is wrong. This integration means people book their holiday once, in HR, and the whole platform knows about it. --- ### Data Exchange Technology The integration is delivered as three separate **Marketplace automations**, each on its own daily schedule — not event-driven: | Automation | Role | Scheduler (as exported) | | --- | --- | --- | | BambooHR - Daily Create Employee | New employees changed/inserted in BambooHR since yesterday → created as Users | **Disabled** (`isActive: false`) | | BambooHR - Daily Employee Update | Employees updated in BambooHR since yesterday → matching User fields updated | **Active** | | BambooHr - Leaves Update | Time-off requests for the company's close-vacations period → leave created/updated/deleted in Skills Workflow | **Disabled** (`isActive: false`) | Each run calls BambooHR's "changed employees" endpoint (`GET /v1/employees/changed?since=&type=...`), then for every id returned fetches that employee's full record (`GET /v1/employees/{id}?fields=...`) and applies it. Reading the current state rather than trusting the event/list payload means a run that's late or picks up the same id twice still leaves Skills Workflow correct. Source: `[BambooHR] [Integrations] Daily Create Employee v17 (Automation) {Active}.json`, `[BambooHR] [Integrations] Daily Employee Update v15 (Automation) {Active}.json`, `[BambooHR] [Integrations] Leaves Update v17 (Automation) {Active}.json`, plus 8 supporting named queries (`BambooHr-GetSkillsInformation`, `BambooHr-GerUserByExternalId`, `BambooHr-UserExists`, `BambooHr-GetSupervisorByExternalId`, `BambooHr-GetsupervisorByEmail`, `BambooHr-GetUserLeaveInformation`, `BambooHr-GetUserLeavesForYear`, `BambooHr-GetCompanyCloseVacationsPeriod`). --- ### Data Exchange (To Skills Workflow) **Employees** New employees in BambooHR are created as Users in Skills Workflow: | Field | Source | | --- | --- | | User | The BambooHR ID, stored in **BambooId** | | UserName | The user's e-mail from BambooHR | | Name | The user's full name | | Typology | Created if it does not exist | | Typology Group | Created if it does not exist | | Department | The BambooHR ID, stored in **BambooId** on the department | | Responsible | The user's supervisor in BambooHR | | Required Hours | The working hours held in BambooHR | | E-mail | The user's e-mail | | Hire Date | The user's hire date | **Time off** For each employee, the automation reads their time-off requests from BambooHR across **every** status — approved, denied, requested, superseded and cancelled — and reflects them in Skills Workflow: - A request that does not yet exist in Skills Workflow is created as leave and sent for approval. - The leave is then approved or rejected so that its state matches the decision recorded in BambooHR. Reading all statuses, rather than only approved ones, is what allows a holiday that was later cancelled or denied in BambooHR to be corrected in Skills Workflow instead of being left blocking the calendar. Leave is matched per employee and per day, so re-running the automation does not create duplicates. --- ### Where This Data Is Used - **User data** appears in the User Profile, and in Resourcing and Contracted Time. - **Absence data** appears in approvals and scheduling. - **FTE and Timesheets** use both. --- ### What the Agency Needs to Provide - A BambooHR account with API access, the company domain, and an API key (read via a `Config` configuration key referenced by all three automations — its exact name and value are not part of the export). - Confirmation of which Skills Workflow leave types the BambooHR time-off types map onto. --- ### Package Contents To enable this integration, install the package from the Marketplace. As exported it contains three automations (`BambooHR - Daily Create Employee`, `BambooHR - Daily Employee Update`, `BambooHr - Leaves Update`) and 8 supporting named queries — not the single automation + single query previously documented here. --- ### Security - All three automations poll BambooHR outbound, on a schedule — there's no public/inbound endpoint or shared key involved in what's exported (the previous "public endpoint with a shared key" description doesn't match; not determinable whether an older version worked that way). - All data is encrypted in transit and at rest. - PII, and therefore GDPR compliance for the source data, remains controlled by BambooHR. - The BambooHR API key is stored in Skills Workflow as a configuration key, not inside the automation. --- ### Good to Know - Users and leave are matched by the BambooHR ID. It should not be edited manually. - The integration is one-way. Leave approved in Skills Workflow does not create a request in BambooHR — HR remains the place where time off is booked. - Because it is event-driven, leave that already existed before the integration was switched on is not backfilled automatically. --- ## Box URL: https://documentation.skillsworkflow.com/docs/integrations/cloud-storage/box Summary: Box is where the organisation's files live, with its own sharing, permissions, versioning and compliance controls. ### Description This article describes the integration between **Box** and `Skills Workflow`. Box is where the organisation's files live, with its own sharing, permissions, versioning and compliance controls. Skills Workflow is where the work those files belong to is run. The integration means neither has to be given up. Files stay in Box — governed by Box's security, and reachable by everyone who already works there — while the people delivering the work upload, preview and find them from inside the job in Skills Workflow, without switching tools or hunting for the right folder. Two things make that work: - **The folder structure builds itself.** Creating a client, a project or a job in Skills Workflow creates the matching folder in Box, nested correctly, following the agency's own template. Nobody creates folders by hand, and nobody has to remember the naming convention. - **Files are accessed as the person, not as the system.** Uploads and previews run under the individual user's own Box permissions, so what someone can see in Skills Workflow is exactly what they are entitled to see in Box. The result is that the file is in one place, once, with one set of permissions — and it is reachable from the job without anyone maintaining a parallel folder tree. --- ### What the User Sees - **Folders appear automatically** as clients, projects and jobs are created, following the hierarchy Client → Project → Job → the agency's job folder template. - **Files are uploaded from inside Skills Workflow**, straight into the mapped Box folder. - **Files are previewed in place**, without downloading them or opening Box. - **Comments and annotations** can be made on the file, when enabled. - **Shared links stay consistent** between the two systems. --- ### What the Agency Needs to Provide - **A Box account and a custom Box App**, configured as described below, with the client id and secret held in Skills Workflow. - **A job folder template** defining the folders each new job should get. - **Matching e-mail addresses** between Skills Workflow and Box, since this is how a user is identified in order to act under their own permissions. --- ### Good to Know - **Permissions come from Box.** Skills Workflow does not grant access to files; a user sees what their Box account allows. - **Each record stores its Box folder reference**, which is what links the two — see the *Box Folder* field below. - **Client folder creation is currently switched off** in this configuration; project and job folders are unaffected. See the export reference at the end of this page. --- ## 1. Overview The **Box integration** allows automatic management of folders and files directly from the Skills Workflow platform, maintaining a synchronized hierarchy of clients, projects, and jobs with the organization’s Box environment. The goal is to centralize document and file management within Skills Workflow while retaining Box’s collaboration and security features. --- ## 2. Authentication The integration uses the **OAuth2 Client Credentials** flow configured in a custom **Box App**. **Required configuration in the Box App:** - Enable the following options: - “Allow as-user header” - “Generate user access token” **Keys and tokens:** - `Client ID` and `Client Secret` are obtained from the Box App and configured in the Skills Workflow **System Parameters**. - Access tokens are generated through an **automation workflow** in Skills Workflow. - Application tokens are used to create global folders. - User tokens are used to upload and access files according to user permissions. - The **refresh token** is automatically managed by the backend through an automation workflow. --- ## 3. Supported Flows - Automatic folder creation based on the Skills structure: - Client > Project > Job > Job folders template (Job folders templates are defined in the System Parameters.) - File uploads are performed directly in Skills through the embedded **Box widget**, respecting the mapped Box folder. - File preview directly inside Skills. - Synchronization of shared links between Box and Skills. - Automatic folder creation when new objects (Clients, Projects, Jobs) are created in Skills. --- ## 4. Folder Configuration (User Field) Each **Job** or **Document** includes a *User Field* named `Box Folder` that stores the **Box Folder ID**. This ID is used by the Box uploader to associate uploaded files with the correct folder. --- ## 5. Webhooks Webhooks are configured within **Skills Workflow** to trigger **folder creation in Box** when documents or jobs are created. These webhooks are internal to Skills Workflow and connect directly to automation workflows responsible for folder management. --- ## 6. Automation Workflows **Automation workflows** can automatically create and map Box folders. **Example:** - **Trigger:** `Job Created` - **Actions:** 1. `Create Box Folder` 2. Update the `Box Folder` user field in the Job. This ensures every new job is immediately associated with its corresponding Box folder following the defined hierarchy. --- ## 7. Skills Workflow Configuration ### Global Activation Navigate to: `Maintenance > Configurations > System > Preview > Box Integration` Enable the option: **Enabled** ### Additional Options - Enable **Box Annotations** to allow commenting directly in Box. - Define file **access levels** according to user roles. - At document level: `Document > Configurations > FileSystem > Enable Box` ### User Mapping - User mapping is based on the **email address** in the user’s Skills profile. - The same email must exist in Box. - The Box App User must have access to these users to obtain their **Box User ID** and perform file operations under their permissions. --- ## 8. Common Errors and Debugging | Issue | Probable Cause | Solution | |--------|----------------|-----------| | “BoxNoFolderConfigured” | Missing *Box Folder* field value | Verify if the automation workflow created the folder correctly | | Token expired | Session expired or refresh token error | Trigger new OAuth2 authentication | | Upload not visible in Box | Folder creation automation failed | Check automation workflow logs | | User cannot access file | Incorrect email mapping | Confirm user email in Box matches Skills profile | | Webhook not triggering | Incorrect configuration | Review webhook or automation trigger setup | --- ## 9. Marketplace Export Reference ### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Box - Create client folder | Webhook | 1 | Active | Fires on Commercial Client creation | | Box - Create client folder | Automation | 2 | **Disabled** (`active: false` in the export) | Would create the client's Box folder — currently switched off | | Box - Create job folder | Webhook | 1 | Active | Fires on Deliverable (job) creation | | Box - Create job folder | Automation | 3 | Active | Creates the job's Box folder | | Box - Create project folder | Webhook | 1 | Active | Fires on Project creation | | Box - Create project folder | Automation | 4 | Active | Creates the project's Box folder | | Box - Get access token | Automation | 5 | Active | Shared helper: gets an enterprise (app) or per-user Box access token | | Box - Ziflow - Create temporary shared link | Automation | 1 | Active | Creates temporary Box shared links for a list of files, for use by [Ziflow](../ziflow) | | Box | System Parameter | 1 | Active | Box app credentials (Developer Token, Client Id/Secret, Box Subject Id/Type, Grant Type, Root Folder) | | Box | Workspace | 1 (Job) / 2 (Project) / 2 (Commercial Client) | Active | The embedded Box panel shown on Job, Project and Commercial Client records | | GetParentBoxFolderId | Query | 1 | Active | Looks up a Deliverable's parent folder id, to nest a job folder under its project | Source: `[Box] [Integrations] Box - Create client folder v1 (Webhook) {Active}.json`, `[Box] [Integrations] Box - Create client folder v2 (Automation) {Active}.json`, `[Box] [Integrations] Box - Create job folder v1 (Webhook) {Active}.json`, `[Box] [Integrations] Box - Create job folder v3 (Automation) {Active}.json`, `[Box] [Integrations] Box - Create project folder v1 (Webhook) {Active}.json`, `[Box] [Integrations] Box - Create project folder v4 (Automation) {Active}.json` (exported 3 times, same content), `[Box] [Integrations] Box - Get access token v5 (Automation) {Active}.json`, `[Box] [Integrations] Box - Ziflow - Create temporary shared link v1 (Automation) {Active}.json`, `[Box] [Integrations] Box v1 (System Parameter) {Active}.json`, `[Box] [Integrations] Box v1 (Workspace) {Active}.json`, `[Box] [Integrations] Box v2 (Workspace) {Active}.json` (job/project/client variants), `[Box] [Integrations] GetParentBoxFolderId v1 (Query) {Active}.json`. Unlike the job and project folder automations, `Box - Create client folder` (v2) is exported with `"active": false` — its webhook is still Active and will fire, but the automation it calls will not create a folder. As exported, new clients do not get an automatic Box folder; only projects and jobs do. ### How It Works - Each of the three "Create ... folder" automations calls `Box - Get access token` (via `ExecuteIntegrationWorkflow`) for an app-level token, then `POST https://api.box.com/2.0/folders` to create the folder (job folders look up their parent project's folder id via `GetParentBoxFolderId` so they nest correctly), and writes the new folder id back onto the record's `Box Folder` custom field (`PUT /api/v3/documentUserFieldValues`). - `Box - Get access token` exchanges the app credentials from the `Box` System Parameter for an enterprise access token (`POST https://api.box.com/oauth2/token`, `grant_type` from the parameter). If the caller passes an `x-userid` header, it additionally looks up that Skills Workflow user's e-mail and resolves the matching Box user (`GET https://api.box.com/2.0/users?filter_term=`), for operations that should run as that person rather than the app. - `Box - Ziflow - Create temporary shared link` gets an access token the same way, then loops over a list of files and creates a temporary shared link for each (`PUT https://api.box.com/2.0/files/{id}?fields=shared_link`) — this is what feeds Box file previews into [Ziflow](../ziflow) proofing. ### Configuration - System Parameter **`Box`** — `DeveloperAccessToken`, `ClientId`, `ClientSecret`, `BoxSubjectId`, `BoxSubjectType`, `GrantType`, `RootFolder`. Values are redacted in the export. - Custom field **`Box Folder`** on Job/Project/Commercial Client — stores the Box folder id. ### Open Questions - Whether client-folder auto-creation being disabled is intentional (e.g. client folders are created some other way) or an oversight is not determinable from the export. --- ## CETA URL: https://documentation.skillsworkflow.com/docs/integrations/ceta Summary: CETA is the agency's job and financial back office. ### Description This article describes the integration between **CETA** and `Skills Workflow`. CETA is the agency's job and financial back office. This integration splits the responsibilities cleanly between the two systems, so each one owns what it is best at: - **Skills Workflow owns the commercial master data** — clients and products are managed there and pushed to CETA. - **CETA owns the work** — projects and jobs are opened in CETA and pulled into Skills Workflow. - **Skills Workflow owns the time** — approved timesheets are sent back to CETA for costing and billing. The result is that teams plan and record work in Skills Workflow, while CETA remains the system of record for the job structure and the financials, with no manual re-keying at any point. --- ### Data Exchange Technology The exchange runs over **REST services** between the two systems. No file transfer and no locally installed application are required. --- ### What Goes Out To CETA | Sent to CETA | Notes | | --- | --- | | Clients | New clients created in Skills Workflow are created automatically in CETA, and later changes are synchronised | | Products | Same — created and kept in step with Skills Workflow | | Timesheets | Only **approved** timesheets are sent | Sending only approved time is deliberate: CETA receives figures the agency has already signed off, so nothing has to be reversed downstream because somebody was still editing their week. --- ### What Comes Into Skills Workflow | Received from CETA | Notes | | --- | --- | | Projects | Imported when they reach **Pencil** or **Confirmed** status in CETA | | Jobs | All jobs are imported. Only **approved** jobs are offered as timesheet suggestions | Importing projects from the "Pencil" stage means the teams can see and plan against work that is still being negotiated, while the timesheet suggestion rule ensures people only book time to jobs that are actually approved. --- ### What the Agency Needs to Provide - Network access between CETA and Skills Workflow, and the credentials for the CETA services. - Agreement on which identifiers link clients, products, projects and jobs across the two systems. - Confirmation of which Skills Workflow timesheet approval state counts as approved for export. --- ### Good to Know - Clients and products are managed in Skills Workflow. Editing them in CETA will be overwritten. - Projects and jobs are managed in CETA. They cannot be created in Skills Workflow and pushed the other way. - A job that has not been approved in CETA is still visible in Skills Workflow — it simply will not be suggested when somebody fills in a timesheet. --- For the field-by-field mappings, see the **[Technical Reference](./reference)**. --- ## CETA — Technical Reference URL: https://documentation.skillsworkflow.com/docs/integrations/ceta/reference Summary: There was a need to exchange data between CETA and Skills Workflow --- Service REST. This page is the interface specification for the CETA integration — file formats, naming conventions and field-by-field mappings. It is written for the team implementing the exchange. For what this integration does and how it is configured, see **[CETA](./)**. ### Description There was a need to exchange data between CETA and Skills Workflow --- ### Data Exchange Technology Service REST. The scope of data exchanged on this integration includes: - Master data - Clients & Products - From Skills Workflow to CETA - Projects & Jobs - Projects are imported into Skills Workflow when in "Pencil" and "Confirmed" status on CETA - All Jobs are imported into Skills Workflow - However, only approved jobs are timesheet suggestion - From CETA to Skills Workflow - Timesheets - Approved Timesheets - From Skills Workflow into CETA --- ### Data Exchange This section describes the Data exchanged between systems. Please see below the data exchanged. Clients are managed in Skills Workflow. - New clients created in Skills Workflow are automatically created in CETA. - Any change in the client data is also synched with CETA. #### Client Data Exchanged Fields that are populated in CETA are: - Name - External Id - Status - Address - Zip Code - Country - Client Manager #### Mappings ``` Name - Client Name - Name External Id - Client External Id - A/c Code Status - Client Status - Status Address - Client Address - Address Zip Code - Client Zip Code - Postal Code Country - Client Country - Country Client Manager - Client Manager - (?) ``` Products are managed in Skills Workflow. New products created in Skills Workflow are automatically created in CETA. Any change in the client data is also synched with CETA. #### Product Data Exchanged Fields that are populated in CETA: - Name - External Id - Status #### Template ``` Client Name - Client Name - Company Name (?) Name - Product Name - Name External Id - Product External Id - (?) Status - Product Status - Status ``` Projects are created in CETA and sent to Skills Workflow when in New state. - The project gets Confirmed as soon as the first Bid/Job is confirmed - As soon as the project status changes, it will be updated in Skills Workflow #### Project Data Exchanged Fields that are populated into Skills: - Title - Status - Number - Type - Client - Product - Project Owner - Start Date - End Date #### Template ``` Title - Project Title - Title Status - Project Status - Status Number - Project Number - Project # Type - Project type - Project Type Client - Project's Client - Client Product - Project's Product - Product Project Owner - Project Owner - 'executiveproducer' Post Producer (Unique external id) Start Date - Project Start Date - Start Date End Date - Project End Date - End Date ``` Jobs are created in CETA and sent to Skills Workflow. - All non-confirmed status jobs are imported - Only confirmed jobs prepopulate the user's timesheet #### Jobs Data Exchanged The fields that are populated into Skills Workflow: - Id - Project Type - Product - Project # - Client Name - Title - Start Date - End Date - Job Type - Resources - Status #### Template ``` Number - Job Number - Id ?? - Quote Id Project Type - Job's Project Type - Project Type Product - Job's Product - Product Project Number - Job's Project Number- Project # Client - Job's Client Title - Job Title Start Date - Job Start Date End Date - Job End Date ``` Timesheets are inputted in Skills Workflow and sent to CETA. - Only approved hours are sent to CETA #### Time Sheet Data Exchanged The fields that will be populated into CETA: - Id - Company - Department - Client - Product - Project - Job - Time type - Work type - User - Status - Timesheet date - Create date - Approval date - Hours #### Template ``` Id - Unique Id Company - Company Code Department - Department External Id Client - Client External Id Product - Product External Id Project - Project Number Job - Job Number Time type - 1 - Billable, 2 - Admin, 3 - Not Billable Work type - Work Type External Id User - User External ID Status - Approved Status Timesheet date - Timesheet Date Create date - Created On Date Approval date - Approval On Date Hours - Amount of hours ``` ### Conclusion The contents of this document create the foundation for data and process communication methodology between Skills Workflow and Agencies. The current known data and process transfers are contained in this document but more may be created as additional data and process needs are discovered. --- ## Client and Agencies URL: https://documentation.skillsworkflow.com/docs/integrations/Client-and-Agencies Summary: Some clients run Skills Workflow themselves. This is not a connection to an external product — it's a bridge between **two separate Skills Workflow tenants**: an agency's own tenant and its client's own tenant. The Marketplace export ships it as two packages, `Client and Agencies (Agency)` and `Client and Agencies (Client)`, one installed on each side. Both halves are documented together on this page. ### Description This article describes the **Client and Agencies** integration between two `Skills Workflow` environments. Some clients run Skills Workflow themselves. When they do, the client's marketing team and the agency delivering the work are both in the same product — but in separate environments, each with its own users, data and security. That separation is the point: neither side wants the other inside their tenant. This integration bridges the two without collapsing them. The client raises and follows work in their own environment; the agency plans and delivers it in theirs; and the job, its stage and the conversation around it stay in step across the boundary. What it replaces is the status e-mail. Without it, the client asks where something is, someone at the agency checks and replies, and the client's own system holds a stale copy of the truth. With it, the client sees the stage move and the comment appear in their own environment, as it happens, without the agency having to tell them. The bridge is deliberately selective: only what the agency marks as client-visible crosses over, and only for the stages the agency has chosen to share. --- ### Data Exchange Technology Each side installs its own package — one on the agency's environment, one on the client's. The two call each other directly over the web, each authenticating with a shared secret the other checks before accepting anything. The exchange is **event-driven in both directions**: it runs when a job's stage changes or a comment is posted, not on a schedule. --- ### Data Exchange (Client → Agency) When a job's stage changes in the client's environment, it is sent to the agency, where: - the **project is created** if the agency does not have one for it yet; - the **job is created or updated** underneath it; - the right **team member is assigned** to it. This is how work raised by the client arrives in the agency's environment ready to be picked up. --- ### Data Exchange (Agency → Client) When someone at the agency posts a comment on a job, it is sent to the client's environment, where it appears as a comment on their copy of the job — and, if the job also moved to a stage the agency has chosen to share, their job moves to that stage too. Only comments marked as visible to the client cross over, and only the stages listed in the agency's configuration. Internal discussion and internal stages stay internal. --- ### What the Agency Needs to Provide - **Both environments' addresses**, and a shared secret agreed between them. - **The list of stages** on the agency side that are eligible to be shared with the client. - **Matching client, company and product records** on the agency side for the work the client sends — see *Good to Know*. --- ### Monitoring and Error Handling If work arrives from the client for a company or a client record the agency's environment does not recognise, the integration does not guess. It stops and sends an e-mail alert, so the missing mapping can be added and the work re-sent, rather than a project being created against the wrong client. --- ### Good to Know - **The client and company have to be mapped on the agency side first.** This is the most common reason work does not come through. - **Nothing crosses over by default.** A comment is only shared if it is marked visible to the client, and a stage change is only shared if that stage is in the agreed list. - **Both sides keep their own security.** Users of one environment never gain access to the other; only the specific records above are exchanged. - Each environment can be upgraded, configured and administered independently — the bridge only depends on the two agreeing on the shared secret and the stage list. --- ### Technical Reference #### Components **Agency side** (`[Client and Agencies (Agency)] [Integrations] ...`): | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | CA-Agency-HandleActivity | Automation | 2 | Active | Receiving endpoint: accepts a job/project update pushed from the client tenant and applies it | | CA-Agency-JobUpdated | Automation | 1 | Active | Sending side: pushes a client-visible comment/stage update to the client tenant when a Post is created | | CA-Agency-Post-Created | Webhook | 1 | Active | Fires `CA-Agency-JobUpdated` whenever a Post is created | | CA-Agency-Integration | System Parameter | 1 | Active | Holds the shared integration secret, the client tenant's connection details, and which stages are pushed to the client | | CA-Agency-Project-Get | Query | 2 | Active | Resolves what to do with an incoming project update: exists / create / company or client not found | | CA-Agency-Job-Get | Query | 2 | Active | Resolves what to do with an incoming job update | | CA-Agency-JobDetails-Get | Query | 1 | Active | Builds the outbound payload describing a job/post for the client tenant | | CA-Agency-ProjectAssignment-Get | Query | 2 | Active | Looks up the user/team to assign on a newly created job | **Client side** (`[Client and Agencies (Client)] [Integrations] ...`): | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | CA-Client-Job-StageUpdated | Automation | 3 | Active | Sending side: pushes a job's data to the agency tenant when its stage changes | | CA-Client-Job-StageUpdated | Webhook | 2 | Active | Fires the automation above on `StageUpdated` for a Deliverable | | CA-Client-ReceivedActivity | Automation | 1 | Active | Receiving endpoint: accepts an activity/stage update pushed from the agency tenant and applies it | | CA-Client-Integration | System Parameter | 1 | Active | Holds the agency tenant's connection details, the receiving webhook id, and the shared integration secret | | CA-Client-Job-Get | Query | 2 | Active | Builds the outbound payload describing a job for the agency tenant | | CA-Client-JobUpdateFromRequest-Get | Query | 2 | Active | Resolves an incoming agency update against the client's own job/workflow | Source: `[Client and Agencies (Agency)] [Integrations] CA-Agency-HandleActivity v2 (Automation) {Active}.json`, `[Client and Agencies (Agency)] [Integrations] CA-Agency-JobUpdated v1 (Automation) {Active}.json`, `[Client and Agencies (Agency)] [Integrations] CA-Agency-Post-Created v1 (Webhook) {Active}.json`, `[Client and Agencies (Agency)] [Integrations] CA-Agency-Integration v1 (System Parameter) {Active}.json`, `[Client and Agencies (Agency)] [Integrations] CA-Agency-Project-Get v2 (Query) {Active}.json`, `[Client and Agencies (Agency)] [Integrations] CA-Agency-Job-Get v2 (Query) {Active}.json`, `[Client and Agencies (Agency)] [Integrations] CA-Agency-JobDetails-Get v1 (Query) {Active}.json`, `[Client and Agencies (Agency)] [Integrations] CA-Agency-ProjectAssignment-Get v2 (Query) {Active}.json`, `[Client and Agencies (Client)] [Integrations] CA-Client-Job-StageUpdated v3 (Automation) {Active}.json`, `[Client and Agencies (Client)] [Integrations] CA-Client-Job-StageUpdated v2 (Webhook) {Active}.json`, `[Client and Agencies (Client)] [Integrations] CA-Client-ReceivedActivity v1 (Automation) {Active}.json`, `[Client and Agencies (Client)] [Integrations] CA-Client-Integration v1 (System Parameter) {Active}.json`, `[Client and Agencies (Client)] [Integrations] CA-Client-Job-Get v2 (Query) {Active}.json`, `[Client and Agencies (Client)] [Integrations] CA-Client-JobUpdateFromRequest-Get v1 (Query) {Active} - Query.json`. #### How It Works **Client → Agency:** 1. On the client tenant, `CA-Client-Job-StageUpdated`'s webhook fires on `StageUpdated` for a `Deliverable`. 2. The automation reads the `ca-client-integration` configuration key, looks up the job via `CA-Client-Job-Get`, and — if found — builds the destination URL from the job's own tenant field: `https://apiv2-{job.tenant}.skillsworkflow.com/api/integration-workflows/{Config.webhook}/execute`. 3. It `POST`s the job data, Base64-encoded, to that URL with header `x-integrationsecret: {Config.integrationSecret}` — landing on the agency tenant's `CA-Agency-HandleActivity`. 4. `CA-Agency-HandleActivity` validates the `x-integrationsecret` header against its own `ca-agency-integration` configuration key; a mismatch exits without processing. 5. It decodes the request body from Base64 and runs `CA-Agency-Project-Get`, which returns an `action`: `EXISTS` (job already has its project — go straight to job creation/update), `CREATE` (project needs creating first), or `COMPANYNOTFOUND` / `CLIENTNOTFOUND` (the incoming company or client isn't recognized on the agency tenant). 6. On `COMPANYNOTFOUND` / `CLIENTNOTFOUND`, an email alert ("BB Error - ...") is sent to `helder.barreiros@skillsworkflow.com` and processing stops. 7. Otherwise the project is created if needed, then the job is created/updated (`CreateJob` sub-workflow, using `CA-Agency-Job-Get`), and `AddJobAssignment` assigns the right user/team via `CA-Agency-ProjectAssignment-Get` and `POST /api/posts`. **Agency → Client:** 1. On the agency tenant, `CA-Agency-Post-Created` fires on every `Post` created. 2. `CA-Agency-JobUpdated` only proceeds for posts on the right document type, then calls `CA-Agency-JobDetails-Get` with the post/event id and the list of "valid stages" from the `ca-agency-integration` configuration key. 3. If the query reports the underlying job/post as `found`, the resulting data is `POST`ed to the client tenant's own webhook endpoint (`https://apiv2-{Config.client.tenant}.skillsworkflow.com/api/integration-workflows/{Config.client.automationId}/execute`), authenticated with an `x-api-auth` header — landing on the client tenant's `CA-Client-ReceivedActivity`. 4. `CA-Client-ReceivedActivity` runs `CA-Client-JobUpdateFromRequest-Get` against the incoming payload. If the status is `found` (a stage transition applies), it creates a client-visible comment **and** transitions the Deliverable's stage in one call (`POST /api/v3/posts`, `isVisibleToClient: true`, with a `transition` action). If the status is `found Job` (the job matched but no valid transition applies), it posts the comment only, without changing the stage. Otherwise it exits without creating anything. #### External System Contact Points - Agency → client tenant: `POST https://apiv2-{client.tenant}.skillsworkflow.com/api/integration-workflows/{client.automationId}/execute`, header `x-api-auth`, landing on `CA-Client-ReceivedActivity`. - Client → agency tenant: `POST https://apiv2-{job.tenant}.skillsworkflow.com/api/integration-workflows/{webhook}/execute`, header `x-integrationsecret`, landing on `CA-Agency-HandleActivity`. - Skills Workflow's own API/analytics on each side: named queries `CA-Agency-Project-Get`, `CA-Agency-Job-Get`, `CA-Agency-JobDetails-Get`, `CA-Agency-ProjectAssignment-Get`, `CA-Client-Job-Get`, `CA-Client-JobUpdateFromRequest-Get`; `POST /api/v3/posts`, `POST /api/posts`. #### Configuration - Agency side, configuration key **`ca-agency-integration`** — `integrationSecret` (validates inbound calls from the client), `client` (the client tenant's name/automation id, used for outbound calls, `x-api-auth`), and `stages` (which workflow stages on the agency side are eligible to be pushed to the client). - Client side, configuration key **`ca-client-integration`** — `agency` (context for the agency side), `webhook` (the agency automation id to call), and `integrationSecret`. - Values for both are not part of the export. #### Open Questions - What "BB" stands for in the agency-side error email subject is not stated anywhere in the export. - The exact set of fields in the job/project payload exchanged between tenants depends on the full SQL of `CA-Agency-JobDetails-Get`, `CA-Agency-Project-Get`, `CA-Agency-Job-Get` and `CA-Client-Job-Get`, not fully explored here. --- ## Cloud Storage URL: https://documentation.skillsworkflow.com/docs/integrations/cloud-storage Summary: Skills Workflow supports integrations with several cloud-based file storage platforms, allowing users to access, preview, and attach documents directly within… Skills Workflow supports integrations with several cloud-based file storage platforms, allowing users to access, preview, and attach documents directly within the platform. These integrations aim to streamline document management processes, enabling real-time access to files stored externally, while maintaining permissions and access control managed by your identity provider. Currently supported providers include: - [Box](box) - [Google Drive](google-drive) - [Microsoft SharePoint](microsoft-sharepoint) --- ### General Configuration Guidelines 1. The integration must be enabled by the Skills Workflow support team for your tenant. 2. An application (client) may need to be registered in the respective platform (e.g. Box, Google Drive or Microsoft SharePoint). 3. The system must be provided with access credentials (client ID, client secret or token) depending on the provider. 4. Permissions should be configured to allow file access, read-only or read-write depending on the intended use. 5. Users must be authenticated in the identity provider that grants access to the external file storage. Skills Workflow does not store external files. All documents remain stored and secured in your cloud provider and are only referenced within the platform. You can control which users have access to each storage provider through role-based permissions or custom rules in your identity provider. --- ### Requirements - Internet access to the storage provider’s API endpoints - Valid credentials (OAuth or token-based) - User mapping between Skills Workflow and the provider (typically via email or UPN) --- ### Support If you need help with the setup or want to enable any of these integrations, please contact the Skills Workflow support team or your technical account manager. --- ## CS (Career Settings) URL: https://documentation.skillsworkflow.com/docs/integrations/cs Summary: Career Settings is the HR system of record. ### Description This article describes the integration between **CS (Career Settings)** and `Skills Workflow`. Career Settings is the HR system of record. This integration takes care of the people side of the platform: it makes sure that every employee who exists in HR also exists in Skills Workflow, with the right company, department, job typology, manager and profile — and that everyone who leaves the organisation is deactivated on time, without HR or IT having to touch Skills Workflow at all. It covers two distinct flows: - **The people file** — the regular export of active employees. - **The terminations file** — the export of leavers, used to deactivate users. --- ### Data Exchange Technology Career Settings drops CSV files on an SFTP server. Skills Workflow connects to that server on a schedule, using key-based authentication, and processes any new files it finds. Files are identified by what their name contains: | Feed | File name contains | Format | | --- | --- | --- | | People | `PDRNon-Confidential-Skills` | `.CSV` | | Terminations | `TerminationDetailsReport` | `.CSV` | Files are processed in order, oldest first. Once a file has been handled it is moved out of the working folder into a **Success** or a **Failure** subfolder, so it is never processed twice and so the agency can always see what happened to a given delivery. The terminations feed is only processed for companies where the **Import Termination Files** setting is enabled. --- ### Data Exchange (To Skills Workflow) **Employee information received** The people file carries the following information for each employee: - Career Settings ID - Preferred Name - Business Title - Employee Class - Legal Entity, and Legal Entity ID - BU Name, and Business Unit ID - Department, and Department ID - LOB1 and LOB2 - Most Recent Hire Date - Email Address - HFM Code - Supervisor, and Supervisor Career Settings ID - LLID **What the integration creates and maintains** From that file, Skills Workflow keeps the following up to date: - **Employees and Users** — new joiners are created automatically; existing people are updated. - **Typologies and Typology Groups** — created when they do not yet exist, and linked to the right companies and departments. - **Responsible (manager)** — set from the employee's supervisor, so the approval chain reflects the HR hierarchy. - **Profiles** — the roles listed in **Default User Profile** are assigned to every new user. - **Leave entitlements** — the leave types configured for the company are attached to each new user. - **Delegate** — when a delegate user name is configured, new users are given that delegate automatically. - **Timesheet requirement** — users whose type appears in **User Types With Required Timesheets** are flagged as needing to fill timesheets. **Leavers** The terminations file inactivates users. The termination date recorded in Skills Workflow is the day before the date supplied by HR. Terminations dated in the future are deliberately left alone and will be applied on a later run, once the date has passed — so somebody leaving next month keeps working normally until they actually leave. When a user is inactivated, a post is created so the change is visible in the platform. --- ### Settings the Agency Controls The integration is configured per company, from the integration settings area in Skills Workflow: | Setting | What it does | | --- | --- | | Ftp Host Ip / Ftp Host Port | Address of the SFTP server | | Ftp Username | User the integration connects with | | Ftp Directory | Folder that is watched for new files | | Ftp Key File Content | Private key used to authenticate | | Default User Profile | Roles assigned to every new user, separated by `;` | | User Updatable | Whether existing users are updated from later files, or only created once | | Disable Responsible Update | Prevents the manager from being overwritten by the HR feed | | Link Company Codes | Company codes, separated by `;`, that should be linked together | | Delegate UserName | User automatically set as delegate for new users | | Timesheets ToApprove Block Enabled | Whether the timesheet approval block applies to imported users | | User Types With Required Timesheets | User types for which timesheets are mandatory | | Import Termination Files | Enables the terminations feed for this company | | Administrator Mail | Address that receives the error notifications for this company | | Log Level Type | How much detail is written to the integration log | --- ### What the Agency Needs to Provide - An SFTP server, the folder to watch, a dedicated user and the private key for that user. - The regular Career Settings exports delivered into that folder, with the expected file names. - The default profile, delegate and typology decisions listed above. - An administrator e-mail address to receive integration notifications. --- ### Monitoring and Error Handling Every run writes to the integration log inside Skills Workflow, at the level of detail chosen in **Log Level Type**. The log is cleared at the start of each run. Problems are reported at file level as well as at record level, so it is possible to see both that a file failed and which specific rows caused it. A summary e-mail is sent to the address configured in **Administrator Mail**. A file that could not be fully imported is moved to the **Failure** folder and can be re-delivered once the underlying issue is resolved. --- ### Good to Know - Employees are matched by their Career Settings ID. That identifier is what ties the HR record to the Skills Workflow user. - **User Updatable** controls whether the HR feed is authoritative after creation. With it disabled, later files will not overwrite manual changes made in Skills Workflow. - **Disable Responsible Update** is useful when the reporting line in Skills Workflow is intentionally different from the HR hierarchy. - Nothing is deleted. Leavers are inactivated and keep their history. --- ## Custom Table Importer URL: https://documentation.skillsworkflow.com/docs/integrations/custom-table-importer Summary: Agencies regularly need data inside Skills Workflow that does not come from any connected system — a rate card, a media plan, a budget breakdown, a list from… ### Description This article describes the **Custom Table Importer**. Agencies regularly need data inside Skills Workflow that does not come from any connected system — a rate card, a media plan, a budget breakdown, a list from a client, a report exported from another tool. Building a dedicated integration for each of those is rarely worth it, but retyping them is worse. The Custom Table Importer solves that. It watches a folder, and every Excel file dropped there becomes a [Custom Table](../administration/custom-tables) inside Skills Workflow — available to views, reports and dashboards like any other data in the platform. No integration project, no development: the agency exports a spreadsheet and drops it in a folder. --- ### Data Exchange Technology The importer runs automatically, **once an hour**, on a folder agreed with the agency. On each run it: 1. Looks in the folder for files matching the configured extension and file-name filter. 2. Reads the first worksheet of each file, using the configured header row to name the columns. 3. Creates the custom table in Skills Workflow — the table name comes from the file name, up to the first digit — and loads the rows into it. 4. Moves the processed file into a **Success** or a **Failure** subfolder. 5. Sends a run summary by e-mail. Rows are uploaded in batches, so large spreadsheets are handled without timing out. --- ### How the Data Lands in Skills Workflow **The file name decides the table name.** Everything up to the first digit in the file name becomes the custom table name. This is what allows the agency to deliver the same table repeatedly — for instance a dated export — and always have it land in the same place. **The header row decides the columns.** The row configured as the header supplies the column names; the rows beneath it become the table rows. **Each load replaces the previous one.** The custom table is recreated on every import, so the table always reflects the latest file rather than accumulating older versions. This also means the file has to be complete: it is a full replacement, not an update of individual rows. **Text is capped.** Values longer than 100 characters are truncated when stored. --- ### Settings the Agency Controls | Setting | What it does | | --- | --- | | Directory Path | The folder that is watched | | File Extension | Which files are picked up | | Filename Contains | Optional filter, so only matching files are imported | | File Row Header | Which row of the worksheet holds the column names | | Chunk Size | How many rows are sent per batch | | Administrator Mail | Address that receives the run summary | --- ### What the Agency Needs to Provide - The folder where the files will be dropped, reachable by the importer. - Agreement on the file naming, so that each file lands in the intended custom table. - The row that contains the column headers, if it is not the first one. - An e-mail address to receive the run summaries. --- ### Monitoring and Error Handling Every run sends a summary e-mail containing the number of rows loaded, any warnings, any errors, and the total running time. A file that could not be fully imported is moved to the **Failure** subfolder and can be corrected and dropped again. A file that imported successfully is moved to **Success**, which keeps the working folder clean and gives the agency a record of what has been processed. --- ### Good to Know - Only the **first worksheet** of each file is read. Additional sheets are ignored. - The import is a full replacement of the table. Anything removed from the file disappears from the custom table on the next run. - Because the table structure is derived from the file, changing the columns in the spreadsheet changes the columns in Skills Workflow — which will affect any view or report built on top of it. - The importer runs hourly, so a file dropped just after a run will be picked up on the next one. --- ## EAS URL: https://documentation.skillsworkflow.com/docs/integrations/eas Summary: EAS holds the agency's people and commercial master data. ### Description This article describes the integration between **EAS** and `Skills Workflow`. EAS holds the agency's people and commercial master data. This integration keeps Skills Workflow aligned with it, so that the platform always reflects the organisation as EAS knows it — the right people, in the right departments, working on the right clients and products — without anyone maintaining two lists. It is the broadest of the file-based integrations, covering both the people side and the commercial side, and it carries results back so the agency can see what happened to each delivery. --- ### Data Exchange Technology Data moves as **JSON files over an SFTP server**. The server is set up by the agency, which provides the credentials to Skills Workflow. Files are separated by purpose: - Files carrying data go in the **Data** directory. - Files requesting a process go in the **Process** directory. Every file name identifies who sent it and what it contains, so both sides can tell at a glance whether a file is inbound, outbound, data, a process command, or a result. The naming convention is part of the contract between the two systems — the exact format is in the technical reference. --- ### What Is Exchanged | Area | What it covers | | --- | --- | | Users | The people who need access to Skills Workflow, with their company, department, manager and working hours | | Leaves | Leave balances, so availability in Skills Workflow reflects entitlement | | Time Sheets | Time data exchanged between the two systems | | Client Groups | The grouping structure above clients | | Clients | The client catalogue | | Products | The product catalogue, under their clients | | Job Jackets | The job structure | | Data Results | The outcome of each processed file, sent back so the agency can confirm what succeeded and what did not | The **Data Results** feed is what makes this integration auditable: rather than assuming a delivery worked, the agency gets a file back stating the result. --- ### What the Agency Needs to Provide - An SFTP server with the **Data** and **Process** directories, and credentials for Skills Workflow. - The EAS exports delivered into those directories, following the agreed file naming convention. - Agreement on which identifiers link a person, client or product across the two systems. --- ### Good to Know - Files are consumed and removed once processed, regardless of the outcome — the result is reported through the Data Results feed rather than by leaving the file in place. - The file name suffix is a timestamp, which also determines processing order when several files of the same type are waiting. - EAS is the source of truth for the data it sends. Manual changes in Skills Workflow to those records will be overwritten by the next file. --- For the file naming rules, JSON templates and field-by-field descriptions, see the **[Technical Reference](./reference)**. --- ## EAS — Technical Reference URL: https://documentation.skillsworkflow.com/docs/integrations/eas/reference Summary: There was a need to exchange data between EAS and Skills Workflow --- The JSON files will be transferred via an SFTP server. This page is the interface specification for the EAS integration — file formats, naming conventions and field-by-field mappings. It is written for the team implementing the exchange. For what this integration does and how it is configured, see **[EAS](./)**. ### Cause There was a need to exchange data between EAS and Skills Workflow --- ### File Transfer Technology The JSON files will be transferred via an SFTP server. The server must be set up by the Agency and credentials must be given to Skills Workflow. Files pertaining to data transfers are to be placed in the Data directory on the SFTP server. Files pertaining to process requests are to be placed in the Process directory on the SFTP server. --- ### File Naming Conventions Each JSON filename will have a prefix, body and suffix. The name will convey information to both Agency and Skills Workflow as to the intent and content of the file as described below. The file name format will be as follows: prefix_body_suffix.json Prefix The filename prefix will consist of two characters. The first character indicates the originator of the file. The second character indicates the type of information contained in the file. First Character - A – Originated by Agency - S – Originated by Skills Workflow Second Character - D – Data - P – Process Command - R – Data/Process Results #### Body The body of the filename is simply used to give a friendly name or to designate specific content. #### Suffix The filename suffix is used to ensure a unique file name and implies a process order when multiple files with the same prefix and body exist. The suffix is simply the date and time relevant to the content of the file in the following format: YYYYMMDDHHmmss. - YYYY – The four character year - MM – The two character month, left padded with a zero when necessary (01-12) - DD – The two character day of the month, left padded with zero when necessary (01-31) - HH – The two character hour, in 24 hour format, left padded with zero when necessary (00-23) - mm – The two character minute, left padded with zero when necessary (00-59) - ss – The two character second, left padded with zero when necessary (00-59) #### File Naming Examples The following are examples of file names. The JSON template details will follow. - AD_LeaveBalance_20180815090119.json – File originated by Agency, containing Leave Balance data to be consumed by Skills Workflow. - AD_LeaveBalance_20180815090119.json – File originated by Skills Workflow, containing the results of the Leave Balance data submitted in the AD_LeaveBalance_20180815090119.json file. - AD_TimeBatch_20180801000000.json – File originated by Agency, containing Time Batch data to be consumed by Skills Workflow. - SR_TimeBatch_20180801000000.json – File originated by Skills Workflow, containing the results of the Time Batch data submitted in the AD_TimeBatch_20180801000000.json file. - SP_CreateJobJacket_20180815144600.json – File originated by Skills Workflow with the process command to create a job jacket. - AR_CreateJobJacket_20180815144600.json – Results file from Agency in response to the command (SP_CreateJobJacket_20180815144600.json) request to create a job jacket ### JSON Templates This section will describe the JSON templates for the currently known exchange processes. The consumer of the JSON files will delete the file from the SFTP server when it has been processed regardless of the process results: success, failure or otherwise. This will contain the user information requested by Skills Workflow. The frequency will be at least once per day but may be a few times per day. The user data is based on a combination of Reach and Active Directory information. Reach data is only captured once per day but Active Directory changes can occur at any time. The integration does not preclude the creation of users manually. In order for users not to be inactivated because they are not in the file, there is a field in the Integrator settings, that allows you to set how many days the user will have before be inactivated if it does not come in the file. - Expiration Days File Name The file name that will always be used for this file: AD_UserAccounts_YYYYMMDDHHmmss.json where the YYYYMMDDHHmmss suffix indicates the as of date. This overrides any previous files information. File Directory This file is to be placed in the Data directory on the SFTP server. Template ``` { { "useraccounts": { "asofdate": "[AS OF DATE]", "recordcount": "[RECORD COUNT]", "users": [ { "userid": "[SAM ACCOUNT NAME]", "personid": "[USER ID]", "company": "[COMPANY]", "fullname": "[FULL NAME]", "divisionid": "[DIVISIONID]", "departmentid": "[DEPARTMENTID]", "position": "[POSITION]", "directmanagerid": "[DIRECT MANAGER SAM ACCOUNT NAME]", "timeapproverid": "[TIMESHEET APPROVER SAM ACCOUNT NAME]", "workphone": "[WORK PHONE]", "email": "[EMAIL]", "username": "[SAM ACCOUNT NAME]", "scheduledhours": "[REQUIRED WEEKLY HOURS]", "contracttype": "[FULL-TIME/PART-TIME/FREELANCER]", "hiredate": "[LATEST HIRE DATE/CREATE DATE]", "enddate": "[TERM DATE/EXPIRATION DATE]" }, { "userid": "[SAM ACCOUNT NAME]", "personid": "[USER ID]", "company": "[COMPANY]", "fullname": "[FULL NAME]", "division": "[DIVISION]", "position": "[POSITION]", "directmanagerid": "[DIRECT MANAGER SAM ACCOUNT NAME]", "timeapproverid": "[TIMESHEET APPROVER SAM ACCOUNT NAME]", "workphone": "[WORK PHONE]", "email": "[EMAIL]", "username": "[SAM ACCOUNT NAME]", "scheduledhours": "[REQUIRED WEEKLY HOURS]", "contracttype": "[FULL-TIME/PART-TIME/FREELANCER]", "hiredate": "[LATEST HIRE DATE/CREATE DATE]", "enddate": "[TERM DATE/EXPIRATION DATE]" } ] } } } ``` useraccounts – Main object - asofdate – Date from which the data is relevant - recordcount – The number of user records contained in the users object list - users – Object that contains a list of user objects. - userid – (UID) - Unique string identifier for a user record - In this case is sent to Skills Workflow the SAM Account Name. - personalid - (UID) - Unique string identifier for a user record - The personalid of the user in EAS. - - company – The code of the company assigned to the user - fullname – The full name of the user - divisionid – The divisionid - will be checked with the SW Division Code - departmentid – The departmentid - will be checked with the SW Department Code - position – The title of the user - directmanagerid – The SAM Account Name of the direct manager - timeapproverid – The SAM Account Name of the time approver - workphone – Work phone number of the user - email – Email address of the user - username – SamAccountName (login name) of the user - scheduledhours – Number of hours the user is scheduled to work in a week - contracttype – Full-Time/Part-Time/Freelancer - hiredate – Actual Hire date for employees, Active Directory created date for Freelancers - enddate – Actual Term date for employees, Active Directory expires date for Freelancers UserAccount file Skills Workflow Description userid SAM Account Name User ExternalId (UID) - Unique string identifier for a user record personalid User Id User ExternalNumber (UID) - Unique string identifier for a user record - it changes everytime that the user change his contract type company CompanyCode Company CompanyCode The code of the company assigned to the user fullname User full name Employee Name The full name of the user divisionid Division Id Division DivisionCode The value must exist in Skills Workflow departmentid Department ID Department DepartmentCode The value must exist in Skills Workflow position User title User UserType The value must exist in Skills Workflow directmanagerid The SAM Account Name of the Direct Manager User ResponsibleExternalId timeapproverid Timesheet Approver N/a N/a workphone Work phone number of the user User Phone email Email address of the user User E-mail username SamAccountName (login name) of the user User SSOUsername scheduledhours Number of hours the user is scheduled to work in a week User Minimum Weekly Hours For minimum daily hours we split the value by 5 contracttype Full-Time/Part-Time/Freelancer User UserType hiredate Actual Hire date for employees, Active Directory created date for Freelancers User HireDate enddate Actual Term date for employees, Active Directory expires date for Freelancers User EndDate This will contain the yearly entitlement for the specific leave types for each employee as well as the time taken for each leave type. File Name The file name that will always be used for this file: AD_LeaveEntitlement_YYYYMMDDHHmmss.json where the YYYYMMDDHHmmss suffix indicates the as of date. This overrides any previous files information. File Directory This file is to be placed in the Data directory on the SFTP server. Template ``` { "leaveentitlement": { "asofdate": "[LONG DATE VALUE]", "recordcount": "[USER RECORD COUNT]", "userentitlement": [ { "userid": "[SAMACCOUNTNAME]", "personid": "[PERSON ID]", "effectivedate": "[EFFECTIVE DATE]", "personalleave": { "personalhours": "[DECIMAL NUMBER OF HOURS]", "personaldays": "[INTEGER NUMBER OF DAYS]", "personaltime": [ { "dataid": "[LONG UNIQUE ID]", "userid": "[SAMACCOUNTNAME]", "personid": "[PERSONIC]", "jobnumber": "[JOB CODE]", "functioncode": "[FUNCTION CODE]", "itemdate": "[ITEM DATE]", "createdate": "[CREATE DATE]", "hours": "[DECIMAL HOURS TAKEN]", "days": "[DECIMAL DAYS TAKEN]" }, { "dataid": "[LONG UNIQUE ID]", "userid": "[SAMACCOUNTNAME]", "personid": "[PERSONIC]", "jobnumber": "[JOB CODE]", "functioncode": "[FUNCTION CODE]", "itemdate": "[ITEM DATE]", "createdate": "[CREATE DATE]", "hours": "[DECIMAL HOURS TAKEN]", "days": "[DECIMAL DAYS TAKEN]" } ] }, "sickleave": { "sickhours": "[DECIMAL NUMBER OF HOURS]", "sickdays": "[INTEGER NUMBER OF DAYS]", "sicktime": [ { "dataid": "[LONG UNIQUE ID]", "userid": "[SAMACCOUNTNAME]", "personid": "[PERSONIC]", "jobnumber": "[JOB CODE]", "functioncode": "[FUNCTION CODE]", "itemdate": "[ITEM DATE]", "createdate": "[CREATE DATE]", "hours": "[DECIMAL HOURS TAKEN]", "days": "[DECIMAL DAYS TAKEN]" }, { "dataid": "[LONG UNIQUE ID]", "userid": "[SAMACCOUNTNAME]", "personid": "[PERSONIC]", "jobnumber": "[JOB CODE]", "functioncode": "[FUNCTION CODE]", "itemdate": "[ITEM DATE]", "createdate": "[CREATE DATE]", "hours": "[DECIMAL HOURS TAKEN]", "days": "[DECIMAL DAYS TAKEN]" } ] }, "vacationleave": { "vacationhours": "[DECIMAL NUMBER OF HOURS]", "vacationdays": "[INTEGER NUMBER OF DAYS]", "vacationtime": [ { "dataid": "[LONG UNIQUE ID]", "userid": "[SAMACCOUNTNAME]", "personid": "[PERSONIC]", "jobnumber": "[JOB CODE]", "functioncode": "[FUNCTION CODE]", "itemdate": "[ITEM DATE]", "createdate": "[CREATE DATE]", "hours": "[DECIMAL HOURS TAKEN]", "days": "[DECIMAL DAYS TAKEN]" }, { "dataid": "[LONG UNIQUE ID]", "userid": "[SAMACCOUNTNAME]", "personid": "[PERSONIC]", "jobnumber": "[JOB CODE]", "functioncode": "[FUNCTION CODE]", "itemdate": "[ITEM DATE]", "createdate": "[CREATE DATE]", "hours": "[DECIMAL HOURS TAKEN]", "days": "[DECIMAL DAYS TAKEN]" } ] } } ] } } ``` - actionType – The actionType must be Rest for Rest actions - name - The name of the action - next - The action that will be triggered after the current action been completed - Method - Should be set according to the method to be applied - url - The URL to be called - bodyMediaType - Allows you to manage the Request headers and body. leaveentitlement – Main Object - asofdate – Date the file was created - recordcount – Number of user accounts in the data - userentitlement – array that contains 1 or more user records - userid – (SSO Name) Unique identifier for each user - personid – Person ID for user - effectivedate – Date the entitlements are effective. Any time taken prior to this date should not be used in any calculation against the entitlement amount. - personalleave – Person Leave object - personaldays – The number of personal days from the effective date to which a user is entitled. - personaltime – An array that contains 0 or more personal time taken objects. - dataid – Unique identifier for time taken record - userid – (SSO Name) – Unique identifier for each user - personid – Person ID for user - jobnumber – Job number for which the time taken pertains - functioncode – Function code for which the time taken pertains - itemdate – The date for which the time taken pertains - createdate – The create date of the time record - hours – The number of hours taken - days – The number calculated days taken based on the hours - sickleave – Sick Leave object - sickdays – The number of sick days from the effective date to which a user is entitled. - sicktime – An array that contains 0 or more sick time taken objects. - dataid – Unique identifier for time taken record - userid – (SSO Name) – Unique identifier for each user - personid – Person ID for user - jobnumber – Job number for which the time taken pertains - functioncode – Function code for which the time taken pertains - itemdate – The date for which the time taken pertains - createdate – The create date of the time record - hours – The number of hours taken - days – The number calculated days taken based on the hours - vacationleave – Vacation Leave object - vacationdays – The number of vacation days from the effective date to which a user is entitled. - vacationtime – An array that contains 0 or more vacation time taken objects. - dataid – Unique identifier for time taken record - userid – (SSO Name) – Unique identifier for each user - personid – Person ID for user - jobnumber – Job number for which the time taken pertains - functioncode – Function code for which the time taken pertains - itemdate – The date for which the time taken pertains - createdate – The create date of the time record - hours – The number of hours taken - days – The number calculated days taken based on the hours This will contain the time posted as requested by Skills Workflow to facilitate time reconciliation. Each file will contain only the time posted since the last file was consumed by Skills Workflow. The frequency will be at least once per day but may be a few times per day. The user data is based on EAS information which can change any time. File Name The file name that will always be used for this file: AD_TimeBatch_YYYYMMDDHHmmss.json where the YYYYMMDDHHmmss suffix indicates the start date/time for this batch of posted time. Each file is unique and does not overwrite any previous data. File Directory This file is to be placed in the Data directory on the SFTP server. Template ``` { { "timebatch": { "batchid": "[BATCH ID]", "batchstart": "[BATCH START DATE]", "batchend": "[BATCH END DATE]", "batchrecordcount": "[RECORD COUNT]", "batchdata": [ { "dataid": "[TIME UNIT ID]", "userid": "[SAM ACCOUNT NAME]", "jobnumber": "[JOB NUMBER]", "functioncode": "[FUNCTION CODE]", "itemdate": "[ITEM DATE]", "createdate": "[CREATE DATE]", "hours": "[HOURS]" }, { "dataid": "[TIME UNIT ID]", "userid": "[SAM ACCOUNT NAME]", "jobnumber": "[JOB NUMBER]", "functioncode": "[FUNCTION CODE]", "itemdate": "[ITEM DATE]", "createdate": "[CREATE DATE]", "hours": "[HOURS]" }] } } } ``` timebatch – Main object - batchid – Unique integer id for each batch - batchstart – Represents the start date and time of data contained in the file - batchend – Represents the end date and time of data contained in the file - batchrecordcount – The number of time records contained in the batchdata object list - batchdata – Object that contains a list of time objects. - dataid – (UID) - Unique long value for the time record. - userid – Unique string identifier for a user record, the SAM Account Name - jobnumber – The Job Number for which the time was posted - functioncode – The Function Code for which the time was posted - itemdate – The specific date for which the time was posted - createdate – The specific date/time the time record was created - hours – The number of hours (quarter hour increments) that was posted To be added to the documentation according to the new definition. The first batch should contain all active clients. All other batches must contain new clients or changes to existing clients only. Note: This file must be consumed before the Product Batch file because the data in the Product Batch file depends on the data from the Client Batch file. File Name The file name that will always be used for this file: AD_ClientBatch_YYYYMMDDHHmmss.json where the YYYYMMDDHHmmss suffix indicates the start date/time for this batch of clients. Each file is unique and does not overwrite any previous data. File Directory This file is to be placed in the Data directory on the SFTP server. Template ``` { "clientbatch": { "batchid": "[BATCH ID]", "batchstart": "[BATCH START DATE]", "batchend": "[BATCH END DATE]", "batchrecordcount": "[RECORD COUNT]", "batchdata": [ { "type": "[NEW/UPDATE]", "company": "[COMPANY]", "clientid": "[UNIQUE IDENTIFIER]", "clientgroup": "[CLIENT GROUP]", "clientcode": "[CLIENT CODE]", "clientname": "[CLIENT NAME]", "clientdescription": "[CLIENT DESCRIPTION]", "clientstatus": "[0 - Active, 1 - Inactive]", "clientcreatedate": "[CLIENT CREATE DATE]", "clientmodifydate": "[CLIENT MODIFY DATE]" }, { "type": "[NEW/UPDATE]", "company": "[COMPANY]", "clientid": "[UNIQUE IDENTIFIER]", "clientgroup": "[CLIENT GROUP]", "clientcode": "[CLIENT CODE]", "clientname": "[CLIENT NAME]", "clientdescription": "[CLIENT DESCRIPTION]", "clientstatus": "[0 - Active, 1 - Inactive]", "clientcreatedate": "[CLIENT CREATE DATE]", "clientmodifydate": "[CLIENT MODIFY DATE]" } ] } } ``` clientbatch – Main object - batchid – Unique integer id for batch - batchstart – Represents the start date and time of data contained in the file - batchend – Represents the end date and time of data contained in the file - batchrecordcount – The number of time records contained in the batchdata object list - batchdata – Object that contains a list of client objects. - type – Indicates if the record is a new client or an attribute for an existing client has changed (NEW – new record, UPDATE – changed record) - company - The code of the company assigned to the client - Company Code - clientid – (UID) – Unique long value for the client record - External Id - clientgroup – The name of the client group assigned in External Source. - Client Group External Id - clientcode – Unique 3-character alpha-numeric code. - Code - clientname – The name of the client - Name - clientdescription – Description for the client, if it exists. - N/a - clientstatus – 0 = Active, 1 = Inactive - Billing Client Status - clientcreatedate – Date client record was created in External Source. - N/a - clientmodifydate – Date of last change recorded for the client record in External Source - N/a The first batch will contain all active products for all active clients. All other batches will contain new products or changes to existing products only. Note: This file must be consumed after the Client Batch file because the data in the Product Batch file depends on the data from the Client Batch file. File Name The file name that will always be used for this file: AD_ProductBatch_YYYYMMDDHHmmss.json where the YYYYMMDDHHmmss suffix indicates the start date/time for this batch of products. Each file is unique and does not overwrite any previous data. File Directory This file is to be placed in the Data directory on the SFTP server. Template ``` { "productbatch": { "batchid": "[BATCH ID]", "batchstart": "[BATCH START DATE]", "batchend": "[BATCH END DATE]", "batchrecordcount": "[RECORD COUNT]", "batchdata": [ { "type": "[NEW/UPDATE]", "company": "[COMPANY]", "productid": "[UNIQUE IDENTIFIER]", "productcode": "[PRODUCT CODE]", "productname": "[PRODUCT NAME]", "productdescription": "[PRODUCT DESCRIPTION]", "productstatus": "[0 - Active, 1 - Inactive]", "productcreatedate": "[PRODUCT CREATE DATE]", "productmodifydate": "[PRODUCT MODIFY DATE]", "clientid": "[CLIENT ID]", "clientgroup": "[CLIENT GROUP]", "clientcode": "[CLIENT CODE]", "clientname": "[CLIENT NAME]", "clientdescription": "[CLIENT DESCRIPTION]", "clientstatus": "[0 - Active, 1 - Inactive]", "clientcreatedate": "[CLIENT CREATE DATE]", "clientmodifydate": "[CLIENT MODIFY DATE]" }, { "type": "[NEW/UPDATE]", "company": "[COMPANY]", "productid": "[UNIQUE IDENTIFIER]", "productcode": "[PRODUCT CODE]", "productname": "[PRODUCT NAME]", "productdescription": "[PRODUCT DESCRIPTION]", "productstatus": "[0 - Active, 1 - Inactive]", "productcreatedate": "[PRODUCT CREATE DATE]", "productmodifydate": "[PRODUCT MODIFY DATE]", "clientid": "[CLIENT ID]", "clientgroup": "[CLIENT GROUP]", "clientcode": "[CLIENT CODE]", "clientname": "[CLIENT NAME]", "clientdescription": "[CLIENT DESCRIPTION]", "clientstatus": "[0 - Active, 1 - Inactive]", "clientcreatedate": "[CLIENT CREATE DATE]", "clientmodifydate": "[CLIENT MODIFY DATE]" } ] } } ``` - actionType - The action type is CreateCsv - name - The action name is custom - next - The next action - hasHeaderRecord - The field to indicate if when exporting the headers should be included - data - The data in JSON to be considered to be exported - dataColumns - The columns that should be exported - delimiter - The columns delimiter e.g. "," , "\t" , ";", etc - quote - The value of the column will be within the character set in the quote e.g. "\"" to make the column values between " productbatch – Main object - batchid – Unique integer id for batch - batchstart – Represents the start date and time of data contained in the file - batchend – Represents the end date and time of data contained in the file - batchrecordcount – The number of time records contained in the batchdata object list - batchdata – Object that contains a list of client objects. - Type – Indicates if the record is a new client or an attribute for an existing client has changed (NEW – new record, UPDATE – changed record) - company - The code of the company assigned to the product - Company Code - productid – (UID) – Unique long value for the product record - External Id - productcode – Unique 3-character alpha-numeric code. - Code - productname – The name assigned to the product record. - Name - productdescription – Description for the product, if it exists. - N/a - productstatus – 0 = Active, 1 = Inactive - Billing Product Status - productcreatedate – Date product record was created in in External Source. - N/a - productmodifydate – Date of last change recorded for the product record in External Source. - N/a - clientid – Unique long value for the client record - Commercial Client External Id - clientgroup – The name of the client group assigned in External Source. - N/a - clientcode – Unique 3-character alpha-numeric code. - N/a - clientname – The name assigned to the client record. - N/a - clientdescription – Description for the client, if it exists. - N/a - clientstatus – 0 = Active, 1 = Inactive - N/a - clientcreatedate – Date client record was created in External Source. - N/a - clientmodifydate – Date of last change recorded for the client record in External Source. - N/a Request Create a Job Jacket Request This will contain instructions that Agency will use to create a job jacket in Nuxeo. This file will be generated when a work order request workflow is in the approved stage in Skills Workflow. File Name The file name that will always be used for this file: SP\_[JOBNUMBER]\_YYYYMMDDHHmmss.json where the placeholder [JOBNUMBER] is replaced by the Job Number indicated in the workflow and the YYYYMMDDHHmmss suffix indicates the date/time that the request was made. File Directory This file is to be placed in the Process directory on the SFTP server. Template ``` { "process": { "name": "CreateJobJacket", "instructions": [ { "name": "CreateJobJacket", "parameters": [ { "name": "jobcode", "value": "[Project Number]" }, { "name": "jobjackettype", "value": "[Project Classification Code]" } ] } ], "emailaddresses": [ { "displayname": "[Approver’s Name]", "email": "[Approver’s Email Address]" } ] } } ``` process – Main object - name – Always “CreateJobJacket” - instructions – Object that contains a list of instructions for the processor to perform - name – Always “CreateJobJacket” - parameters – Object that contains a list of parameter objects as name/value pairs - First Parameter - name – Always “jobcode” - value – The actual job code for which the job jacket needs to be created in Nuxeo - Second Parameter - name – Always “jobjackettype” - value – The name of the job jacket type that will be created in Nuxeo - emailaddresses – Object that contains a list of email addresses to send the success or failure of the job jacket creation process. - displayname – The approvers full name - email – The approvers email address Result Create a Job Jacket Result This will contain results of creating a Job Jacket in Nuxeo for a specific Create Job Jacket Request file. File Name The file name that will always be used for this file: AR*[BODY]*[SUFFIX].json where the [BODY] and [SUFFIX] of the file name will match the Create Job Jacket Request file body and suffix. File Directory This file is to be placed in the Process directory on the SFTP server. Template ``` { "process_results": { "name": "CreateJobJacket", "status": "[SUCCEEDED/QUEUED/FAILED]", "message": "[MESSAGE ABOUT PROCESS]", "process_info": [ { "name": "jobcode", "value": "[Project Number]" }, { "name": "jobjackettype", "value": "[Project Classification Code]" }, { "name": "jobjacketurl", "value": "[Link to Job Jacket in Nuxeo]" } ] } } ``` Template Description process_results – Main object - name – Always “CreateJobJacket” - status – SUCCEEDED/QUEUED/FAILED - message – Message that will provide more details about the status. - process_info – Object that contains a list of name/value pairs that are specific to the CreateJobJacket process. - First process_info item - name – Always “jobcode” - value – The Job Code that was submitted in the request - Second process_info item - name – Always “jobjackettype” - value – The Job Jacket Type that was submitted in the request - Third process_info item (ONLY if job jacket was successfully created) - name – Always “jobjacketurl” - value – The url that links to the specific job jacket in Nuxeo Data Results File This will contain the results of the data file transaction process. The same format is used for all data file transactions. File Name The file name that will always be used for this file: SR*[BODY]*[SUFFIX].json where the [BODY] and [SUFFIX] values are replaced with the respective body and suffix of the data file that was processed. File Directory This file is to be placed in the Data directory on the SFTP server. Template ``` { "data_results": { "status": "[SUCCEEDED/FAILED]", "message": "[MESSAGE ABOUT RESULTS]", "errors": [ { "uid": "[UNIQUE RECORD ID FOR DATA]", "error": "[REASON FOR ERROR]" }, { "uid": "[UNIQUE RECORD ID FOR DATA]", "error": "[REASON FOR ERROR]" } ] } } ``` data_results – Main object - status – Status of process SUCCEEDED/FAILED - message – Message about the results. - errors – Object that contains a list of error objects (if there are errors). - uid – The unique identifier for the data being processed. In this document, this field is designated by the (UID) indicator. - error – The error specific to the record indicated by the uid ### Conclusion The contents of this document create the foundation for data and process communication methodology between Skills Workflow and Agency. The current known data and process transfers are contained in this document but more may be created as additional data and process needs are discovered. --- ## Generic Automations URL: https://documentation.skillsworkflow.com/docs/integrations/Automations Summary: Unlike the other integrations in this section, this one is not tied to a named external system. ### Description This article describes the **Generic Create Project** endpoint in `Skills Workflow`. Unlike the other integrations in this section, this one is not tied to a named external system. It is a ready-made, credential-protected entry point that lets **any** system create a project in Skills Workflow by calling a web address — without a bespoke integration having to be built for it first. That is its value. When a client's intranet, an internal tool, a form, or an automation platform needs to open projects in Skills Workflow, the usual answer is a development project: agree a payload, build an automation, test it, deploy it. This endpoint removes that step for the single most common case. The agency issues a key to whoever needs it, they post the project details, and the project exists. It is deliberately narrow: it creates projects, and nothing else. --- ### Data Exchange Technology The endpoint is a **web address that the calling system posts to** — Skills Workflow does not poll anything and there is no schedule. Every call is authenticated with an application id and secret issued by the agency, sent as request headers. A call without valid credentials is rejected outright. The response is immediate and tells the caller what happened: the created project on success, or the reason it was refused. --- ### Data Exchange (To Skills Workflow) **A request → a Project** The calling system supplies: | Required | Meaning | | --- | --- | | Name | The project's name | | Start date | When the project begins | | Client | The client the project belongs to | | Project nature | The kind of project | | Project owner | The user who will own it — the project is created as though by this person | | Classification | The project's classification | If all of it is present and valid, the project is created and automatically moved to its first available workflow stage, so it arrives ready to work on rather than sitting in a limbo state. --- ### What the Agency Needs to Provide - **An application id and secret** for each system allowed to call the endpoint, held in Skills Workflow's configuration. - **The endpoint address**, given to whoever is integrating. - **Agreement on the values** the caller will send for client, project nature, project owner and classification, since these must correspond to records that already exist in Skills Workflow. --- ### Monitoring and Error Handling Because the caller gets an answer synchronously, failures surface on their side rather than silently in Skills Workflow: | Response | Meaning | | --- | --- | | Unauthorised | The application id or secret was missing or wrong | | Rejected | One or more required fields were missing from the request | | Refused | The details were complete but Skills Workflow could not create the project — the reason is returned | Nothing is created unless the whole request succeeds, so a failed call never leaves a half-made project behind. --- ### Good to Know - **Projects only.** Jobs, briefs and everything else still need their own integration. - **The project is created as the supplied owner**, so it appears in Skills Workflow attributed to a real person rather than to a system account. - The credentials are the usual point of failure — if a system that was working stops creating projects, the key is the first thing to check. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Generic - Create Project | Automation | 1 | Active | Inbound HTTP endpoint that authenticates a request and creates a Skills Workflow project | Source: `[Automations] [Integrations] Generic - Create Project v1 (Automation) {Active}.json`. #### How It Works The automation is exposed as an HTTP endpoint (`isApiCall: true` on every action, no scheduler defined — it runs on demand when called, not on a timer). 1. **Authenticate** (`AuthenticateSW` sub-workflow) — reads the configuration key `Generic-Authentication`, which holds the list of valid `x-appId`/`x-appSecret` pairs, and checks the incoming request's `X-AppId` / `X-AppSecret` headers against it. If either header is missing or doesn't match, the automation returns `401 Unauthorized`. 2. **ValidateRequest** — validates the request body is present and contains `name`, `beginDateUtc`, `clientId`, `projectNatureId`, `projectOwnerId` and `classificationId`. Missing fields return `400` with the validation error as the body. 3. **CreateProject** — `POST /api/v3/projects` with `OperationType: Create` and the request body as `CreateModel`, using `X-AppUser` set to the caller-supplied `projectOwnerId`. A non-`201` response returns `400` with the API's error content. 4. **GetAvailableStages** — `GET /api/workflowStateTransitions?documentTypeName=Skill.Module.BusinessObjects.Project&documentId={projectId}` to find the project's first workflow transition. 5. **MoveStageToFirstAvailable** — `POST /api/posts` with a `Transition` action to move the new project to that first available stage, clearing any previous workflow state. 6. On success, returns `200` with the created project's content. #### External System Contact Points - Inbound: an HTTP endpoint on this automation (URL not present in the export — automations are invoked via their own execute URL, keyed by the automation's id). - Outbound (internal): calls Skills Workflow's own API — `POST /api/v3/projects`, `GET /api/workflowStateTransitions`, `POST /api/posts`. - Auth: custom header pair `X-AppId` / `X-AppSecret`, validated against the `Generic-Authentication` configuration key. #### Configuration - Configuration key **`Generic-Authentication`** — holds the accepted `x-appId` and `x-appSecret` values. Its content is not part of the export. #### Open Questions - Which external system(s) actually call this endpoint is not determinable from the export — the component is generic by design and not scoped to a named third party. - The endpoint URL and the specific caller(s) authorized via `Generic-Authentication` are not determinable from the export. --- ## Google Data Studio URL: https://documentation.skillsworkflow.com/docs/integrations/google-data-studio Summary: Copies Skills Workflow data into Google BigQuery for reporting in Google Data Studio (Looker Studio). ### Description This integration copies Skills Workflow data into **Google BigQuery**. A loader runs in the agency's own Google Cloud project, calls the Skills Workflow data extraction named queries, and writes each one to a table in the `skills_workflow` dataset. Google Data Studio (Looker Studio) is then connected to BigQuery using Google's own BigQuery connector. The agency builds its own reports and charts. The integration delivers the data; it does not deliver reports. Skills Workflow is the source of truth. Nothing written in BigQuery or in a report returns to Skills Workflow. --- ### Requirements - **Skills Workflow API access.** The agency's `tenant` slug, `tenant_id`, `app_id` and `app_secret`. Request these from the Skills Workflow team. Where a user context is required, use a dedicated read-only integration user rather than a person's account. - **A Google Cloud project with billing enabled.** Use a separate project per agency where possible. - **The Google Cloud CLI**, installed and initialised on the machine that runs the installation. - **Google permissions.** The account running the installation must be able to enable APIs, create service accounts, change IAM, build containers, deploy Cloud Run jobs, create secrets, and create Cloud Scheduler jobs. Report authors need BigQuery Data Viewer and BigQuery Job User on that project. --- ### Configuration #### 1. Get the loader package Download the latest loader release, [skills-workflow-bigquery-1.0.1.zip](https://github.com/SkillsWorkflow/GoogleBigQuery/releases/latest). Unpack it and work from the package directory: ```bash curl -LO https://github.com/SkillsWorkflow/GoogleBigQuery/releases/download/v1.0.1/skills-workflow-bigquery-1.0.1.zip unzip skills-workflow-bigquery-1.0.1.zip cd skills-workflow-bigquery-1.0.1 chmod +x scripts/deploy.sh scripts/grant_report_access.sh ``` #### 2. Prepare the tenant credentials Copy `credentials.example.json` to a file kept outside source control and replace the placeholders with the agency's values: ```json { "tenant": "agency-slug", "tenant_id": "tenant-application-id", "app_id": "application-id", "app_secret": "application-secret", "user_id": "optional-operational-user-id" } ``` If the user ID is not known, omit `user_id` and supply `username` and `password` instead. The loader authenticates at the start of each run and uses the user ID it receives. The installation uploads this file to Google Secret Manager. The values are never placed in BigQuery, in the container image, or in a Google Data Studio configuration. Do not email the file or commit it. #### 3. Install the loader Run the installation from the package directory. Use `skills_workflow` as the dataset name: ```bash PROJECT_ID="your-google-cloud-project" \ CREDENTIALS_FILE="/absolute/path/to/credentials.json" \ BQ_DATASET="skills_workflow" \ REGION="europe-west1" \ BQ_LOCATION="EU" \ ./scripts/deploy.sh ``` The installation enables the required APIs, creates the service accounts, uploads the secret, builds the image, deploys the Cloud Run job, and creates the Cloud Scheduler job. It can be re-run to apply a new image, a new secret version, or a changed schedule. These settings are optional and take the defaults below: | Setting | Default | Purpose | | --- | --- | --- | | `REGION` | `europe-west1` | Cloud Run and Scheduler region | | `BQ_LOCATION` | `EU` | BigQuery dataset location | | `BQ_DATASET` | `skills_workflow` | Dataset the tables are written to | | `SCHEDULE` | `0 * * * *` | Cron expression that starts the loader | | `TIME_ZONE` | `UTC` | Timezone for the schedule | | `JOB_NAME` | `skills-workflow-loader` | Cloud Run job name | | `SECRET_NAME` | `skills-workflow-credentials` | Secret Manager secret | | `REPOSITORY` | `skills-workflow` | Artifact Registry repository | Keep Cloud Run and BigQuery in compatible regions. #### 4. Run and verify the first synchronization ```bash gcloud run jobs execute skills-workflow-loader \ --region europe-west1 \ --project your-google-cloud-project \ --wait ``` Open BigQuery in the Google Cloud Console and check the status and row count of each query: ```sql select query_name, status, row_count, finished_at, error_message from `your-google-cloud-project.skills_workflow._sw_sync_runs` order by finished_at desc ``` If a named query is not enabled for the tenant, the other queries still load and the failure is recorded against that query. #### 5. Give report authors access Grant access to a Google group rather than to individual accounts where possible: ```bash PROJECT_ID="your-google-cloud-project" \ MEMBER="group:report-authors@example.com" \ ./scripts/grant_report_access.sh ``` This grants BigQuery Data Viewer and BigQuery Job User. Report authors can query the dataset; they cannot change the loader's secret or its Cloud Run configuration. #### 6. Connect Google Data Studio 1. In Google Data Studio, select **Create → Data source**. 2. Choose Google's **BigQuery** connector. 3. Select the Google Cloud project, the `skills_workflow` dataset, and the table or view you need. Table names follow the named query, so `DE-Projects` becomes `de_projects`. 4. Select **Connect**, review the field types and default aggregations, then select **Create report** and add your charts. 5. Repeat for each additional source. Use data blending for simple combinations, and a BigQuery view for business logic reused across several reports. No Skills Workflow credentials are entered in Google Data Studio. Google IAM controls who reaches the data. --- ### Data updates Cloud Scheduler starts the loader hourly, on the default `0 * * * *` schedule. Each query then has its own refresh interval: operational queries hourly, other transactional queries every four hours, reference data daily. To change an interval for one tenant, set `SW_QUERY_OVERRIDES_JSON` on that tenant's Cloud Run job: ```json { "DE-History": {"enabled": false}, "DE-TimeSheets": {"refresh_minutes": 30, "order_by_field": "TimeSheetId"} } ``` A successful refresh replaces that query's table with a full current snapshot. If a load fails, the previous table stays in place. `_sw_query_catalog` lists the available tables and their refresh intervals. When Skills Workflow adds or changes a returned field, the next successful load updates the BigQuery table schema. Select **Refresh fields** on the Google Data Studio data source before the new field appears in a report. Google Data Studio caches query results. A report can show older figures than BigQuery holds until the report is refreshed. Data in reports is therefore not real-time. BigQuery storage and queries are billed by Google to the agency's Cloud project. Set a billing budget and a BigQuery query quota before sharing report access widely. --- ### Related documentation - [Data Extraction API](/docs/build-and-extend/api/data-extraction-api) — the named queries the loader reads. --- ## Google Drive URL: https://documentation.skillsworkflow.com/docs/integrations/cloud-storage/google-drive Summary: The integration allows you to: --- When a file is uploaded into Google Drive, it is automatically available in Skills Workflow. ### Description The integration allows you to: - Create automatically and organize a file structure in Google Drive - Access to the folders and files available in Google Drive - Let you team get quick and easy access to the files - Share the direct link to the files --- ### Files When a file is uploaded into Google Drive, it is automatically available in Skills Workflow. - You can share your file by going into your document and easily select the file - It will be available to add it into the document's description - Or to post it on document's feed --- ### Folders Not all folders are synched between the two systems: - To launch Google Drive, click on the Cloud icon - There's a root folder setup in Skills Workflow and in Google Drive - Projects must be active and marked as "Deliverable" in the tab "Info" - Jobs must be active, marked as "Deliverable" and his parent as well - To automatically create the Template Sub-Folders, it is necessary to mark both options in the Additional Information tab of Job Google Drive Folder field available in the Additional Information tab of each document: - Will let you map to an existent folder's name - Or to change the respective folder's name Whenever a document is created in Skills Workflow, a folder is created under its parent document folder. The structure of the folders in Skills Workflow is: - Root - Client - Project - Jobs - Sub-Jobs template - Estimate - Expense - User When a folder is created in Skills Workflow, it is created automatically in Google Drive. --- ### Synching The synching is performed by a background process. Whenever a document is created or his folder name is changed in Skills Workflow, the process will replicate it in Google Drive. - The synching process is bi-directional - Skills Workflow has a reference of the ID of the files and folders in Google Drive - The users will see the same file structure (starting on the root) in both systems --- ## Google Suite URL: https://documentation.skillsworkflow.com/docs/integrations/single-sign-on-sso/google-suite Summary: In this article, you'll learn how to integrate with Google Suite SSO. In this article, you'll learn how to integrate with Google Suite SSO. When you integrate Skills Workflow with Google Suite, you can: * Control in Google Suite who has access to Skills Workflow. * Enable your users to be automatically signed-in to Skills Workflow with their Google Suite accounts. --- ### Prerequisites To get started, you need the following items: * An Google Suite subscription. * Skills Workflow single sign-on (SSO) enabled subscription. ### Installation To access the Google panel and configure your custom SAML application, please follow the link: https://support.google.com/a/answer/6087519?hl=en To download the Skills Workflow metadata for uploading to Google Suite, please access the following link: https://auth.skillsworkflow.com/saml2/metadata Kindly send us the metadata so that we can configure it on the Skills Workflow side. --- ## Granatum URL: https://documentation.skillsworkflow.com/docs/integrations/Granatum Summary: Granatum is the agency's financial management platform — where cash flow is planned and where money in and money out is recorded against cost and profit… ### Description This article describes the integration between **Granatum** and `Skills Workflow`. Granatum is the agency's financial management platform — where cash flow is planned and where money in and money out is recorded against cost and profit centres. Skills Workflow is where the work that generates that money is run. The integration keeps the two aligned so that the commercial teams work in Skills Workflow and the finance team keeps working in Granatum, without anyone retyping the same client, supplier or document twice. In practice it takes care of two jobs: - **Bringing the master data in** — clients, suppliers and cost/profit centres that already exist in Granatum are created and kept up to date in Skills Workflow, so documents are raised against the records finance actually uses. - **Posting the financials out** — once a bill or purchase order is approved, it is written into Granatum as a financial entry (*lançamento*), and the reference Granatum assigns is stored back on the document. The result is that approval is posting. Finance stops re-keying approved documents, and every document in Skills Workflow carries the Granatum entry it produced — so anyone can trace one to the other without opening both systems. --- ### Data Exchange Technology The exchange runs over the Granatum web API, using an address and access token configured by the agency. No files and no locally installed application are required. The two directions work differently: - **Posting documents out is event-driven** — it fires when the document reaches the stage that means it is ready. - **Pulling master data in is an on-demand batch**, run when the agency needs to refresh it. --- ### Data Exchange (To Skills Workflow) | Received from Granatum | Becomes in Skills Workflow | | --- | --- | | Clients | Commercial clients and billing clients, with the link to their company | | Suppliers | Suppliers | | Cost and profit centres | Commercial products | Records already imported keep their Granatum identifier, so subsequent runs update the existing record instead of creating a duplicate. --- ### Data Exchange (From Skills Workflow) **Bills and Purchase Orders → Lançamentos (financial entries)** When a bill or a purchase order changes stage, it is sent to Granatum as a financial entry and the result is written back onto the document. The same mechanism serves both document types, so money owed to the agency and money the agency owes are posted the same way. --- ### What the Agency Needs to Provide - **A Granatum account with API access**, plus the address and access token for Skills Workflow. - **Cost and profit centre codes** on the client records that should map to Granatum's. - **The stage** on the Bill and Purchase Order document types that means "ready to post", since reaching it is what triggers the hand-off. --- ### Good to Know - **Master data flows in, documents flow out.** Granatum owns the client, supplier and cost-centre lists; Skills Workflow owns the documents. - **Documents are linked by the Granatum entry reference** stored on them after a successful post. - The master-data refresh is run on demand rather than on a fixed schedule, so it is worth re-running it after a batch of new clients or suppliers is set up in Granatum. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Granatum-Lancamentos | Automation | 1 | Active | Posts a Bill or Purchase Order to Granatum as a financial entry and links it back | | Granatum-Bill-Stage | Webhook | 1 | Active | Fires `Granatum-Lancamentos` when a Bill's stage changes | | Granatum-PurchaseOrder-Stage | Webhook | 1 | Active | Fires `Granatum-Lancamentos` when a Purchase Order's stage changes | | Granatum-Clients | Automation | 1 | Active | Pulls clients from Granatum and creates/updates the matching commercial and billing clients | | Granatum-Suppliers | Automation | 1 | Active | Pulls suppliers from Granatum | | Granatum-Products | Automation | 1 | Active | Pulls cost/profit centers from Granatum as commercial products | | Granatum-Client | Query | 1 | Active | Resolves an existing client for the Clients sync | | Granatum-Supplier | Query | 1 | Active | Resolves an existing supplier for the Suppliers sync | | Granatum-CentroCustosLucro | Query | 1 | Active | Lists clients' cost/profit-center codes to resolve against Granatum | | Granatum-GetLancamentoById | Query | 1 | Active | Builds the financial-entry payload for a Bill or Purchase Order | | Granatum-GetBillItemById | Query | 1 | Active | Resolves a bill item's data (article, VAT) — not called by any automation in this export | Source: `[Granatum] [Integrations] Lancamentos v1 (Automation) {Active}.json`, `[Granatum] [Integrations] Bill Stage v1 (Webhook) {Active}.json`, `[Granatum] [Integrations] Purchase Order Stage v1 (Webhook) {Active}.json`, `[Granatum] [Integrations] Clients v1 (Automation) {Active}.json`, `[Granatum] [Integrations] Suppliers v1 (Automation) {Active}.json`, `[Granatum] [Integrations] Products v1 (Automation) {Active}.json`, and the named queries above. #### How It Works **Posting a financial entry** (webhook-triggered, confirmed by matching automation id `60d2e209-40d5-4309-a7e2-286c93628daf`): either webhook fires `Granatum-Lancamentos` on a `StageUpdated` event for a `Bill` or `PurchaseOrder`. The automation runs `Granatum-GetLancamentoById` to build the entry, `POST`s it to Granatum (`{host}/v1/lancamentos?access_token=...`), and patches the source document with the result (`PATCH /api/bill/{id}` or `PATCH /api/purchase-orders/{id}` depending on which fired it). **Syncing master data** (all on-demand — no scheduler and no webhook in this export triggers them): - `Granatum-Clients`: `GET {host}/v1/clientes` from Granatum, resolves each against `Granatum-Client`, and creates/updates the commercial client, billing client and their company link (`POST /api/v3/commercial-clients`, `POST /api/v3/billing-clients`, `POST /api/v3/commercial-client-companies`, or the matching `PATCH`es on update). - `Granatum-Suppliers`: `GET {host}/v1/fornecedores`, resolved against `Granatum-Supplier`, `POST /api/v3/suppliers`. - `Granatum-Products`: resolves each client's cost/profit-center code (`Granatum-CentroCustosLucro`), fetches it from Granatum (`GET {host}/v1/centros_custo_lucro/{code}`), and creates it as a commercial product (`POST /api/v3/commercial-products`). #### External System Contact Points - Granatum API (`{host}` from the `Config` configuration key, token as an `access_token` query parameter): `GET /v1/clientes`, `GET /v1/fornecedores`, `GET /v1/centros_custo_lucro/{id}`, `POST /v1/lancamentos`. - Skills Workflow's own API/analytics: named queries `Granatum-Client`, `Granatum-Supplier`, `Granatum-CentroCustosLucro`, `Granatum-GetLancamentoById`; `POST /api/v3/commercial-clients`, `POST /api/v3/billing-clients`, `POST /api/v3/commercial-client-companies`, `POST /api/v3/suppliers`, `POST /api/v3/commercial-products`, `PATCH /api/bill/{id}`, `PATCH /api/purchase-orders/{id}`. #### Configuration - A `Config` configuration key (exact name not confirmed beyond the `Config` alias used in the automations) — holds Granatum's `host` and `access_token`. Values are not part of the export. #### Open Questions - What triggers `Granatum-Clients`, `Granatum-Suppliers` and `Granatum-Products` (a schedule configured outside the exported JSON, or a manual action) is not determinable from the export. - `Granatum-GetBillItemById` isn't called by any exported automation — whether it's used by a component outside this export or is unused isn't determinable. --- ## GSP Dynamics Timesheet Importer URL: https://documentation.skillsworkflow.com/docs/integrations/gsp-dynamic-timesheet-importer Summary: Where timesheets are recorded in Dynamics rather than in Skills Workflow, the agency still needs that time visible inside the platform — next to the projects,… ### Description This article describes the **GSP Dynamics Timesheet Importer**. Where timesheets are recorded in Dynamics rather than in Skills Workflow, the agency still needs that time visible inside the platform — next to the projects, the clients and the financials — in order to report on utilisation, billability and delivered hours. This importer takes care of that. It collects the Dynamics timesheet report and loads it into a [Custom Table](../administration/custom-tables) in Skills Workflow, where it can be used by views, reports and dashboards like any other data in the platform. It is a reporting feed. It does not create timesheets in Skills Workflow and does not affect approvals or billing. --- ### Data Exchange Technology The importer runs automatically, **once a day**. On each run it: 1. Connects to the SFTP server where the Dynamics report is published, and looks for the timesheet report file. 2. Reads the year from the file name. 3. Empties the corresponding custom table and loads the file into it. 4. Moves the processed file into a **Success** or a **Failure** folder. 5. Sends a run summary by e-mail. Rows are uploaded in batches, so a full year of timesheet data is loaded without timing out. --- ### How the Data Lands in Skills Workflow **One table per year.** The year is taken from the file name and appended to the table name, so each year of timesheet data lives in its own custom table. This keeps the tables at a manageable size and lets a single year be reloaded without touching the others. **Each load replaces the year.** The table for that year is emptied before the file is loaded, so it always reflects the latest report rather than accumulating duplicates. The report therefore has to be complete for the year it covers. **What each row contains:** | Group | Fields | | --- | --- | | Employee | Employee Name, Employee ID, Reach ID, Title, Employee Division, Department, Division Code | | Client and work | Client, Company, Product, Project Code, Project Name, Project Group Name | | Period | Transaction Month/Year, Week Number, Period Type, Time Sheet Date, Posting Date, Timesheet Status | | Category | Category Code, Category Name, Line Property, Transaction Text | | Hours and value | Hours, Client Hours, Non Client Hours, Billing Rate, Billable Amount, Actuals | | Totals | Total Hours, Total Hours Client, Total Hours Non Client, Total Billable Amount, Total Billing Value | --- ### Settings the Agency Controls | Setting | What it does | | --- | --- | | Host / Port | Address of the SFTP server where the report is published | | Username / Password | Credentials the importer connects with | | Path | Folder that holds the report | | Filename Contains | Identifies the timesheet report among the files in that folder | | File Extension | Which files are picked up | | Custom Table Name | Base name of the custom table; the year is appended to it | | Administrator Mail | Address that receives the run summary | --- ### What the Agency Needs to Provide - The SFTP server, folder and credentials where the Dynamics report is published. - A daily report export delivered into that folder, with the year in the file name. - An e-mail address to receive the run summaries. --- ### Monitoring and Error Handling Every run sends a summary e-mail containing how many rows were removed, how many were loaded, any warnings or errors, and the total running time. A file that could not be fully imported is moved to the **Failure** folder and can be corrected and re-delivered. A file that imported successfully is moved to **Success**, which keeps the working folder clean and gives the agency a record of what has been processed. --- ### Good to Know - This is a read-only reporting feed. Nothing in Skills Workflow is created, approved or billed from it. - The year in the file name determines which table is replaced. A file with the wrong year in its name will overwrite the wrong year of data. - The report must be complete for its year, because the table is emptied before every load. - The importer runs once a day, so the data in Skills Workflow is as fresh as the most recent report delivered. --- ## HR-Link URL: https://documentation.skillsworkflow.com/docs/integrations/hr-link Summary: HR-Link is the HR system of record. ### Description This article describes the integration between **HR-Link** and `Skills Workflow`. HR-Link is the HR system of record. This integration takes care of the people side of the platform: every employee who exists in HR also exists in Skills Workflow, in the right company, department and typology, reporting to the right manager — without HR or IT having to maintain a second list. It is one-way. HR-Link is the source of truth, and Skills Workflow follows it. --- ### Data Exchange Technology The integration calls the HR-Link web services directly. Skills Workflow authenticates first against HR-Link's token service using a key and secret supplied by the agency, and then reads two separate feeds with the token it gets back: | Feed | What it carries | | --- | --- | | Personal data | Who the person is — names, contact details, addresses | | Job data | What the person does — company, business unit, department, job code, employee class, location and supervisor | The two feeds are combined into a single view of each employee before anything is written to Skills Workflow. The integration runs on a schedule, company by company, and picks up what changed since the previous successful run. No files, no FTP server and no locally installed application are required. --- ### Data Exchange (To Skills Workflow) **What is created and maintained** - **Users and Employees** — new joiners are created automatically; existing people are updated. - **Typologies and Typology Groups** — created when they do not yet exist, so the agency does not have to pre-build the structure. - **Departments** — matched by their external identifier against the departments already registered in Skills Workflow. - **Responsible (manager)** — set from the supervisor in the job data feed, so the approval chain reflects the HR hierarchy. **Employee fields populated** Name, UserName, Company, Company Code, Department, Typology, E-mail, Phone, Hire Date, IsActive and SSO Username. **Status handling** The active status coming from HR-Link is written to the **User Active Status** field, so somebody on leave can be told apart from somebody active. Terminated employees are inactivated automatically — nothing is deleted, so history and reporting are preserved. After creation, the fields that continue to be updated from HR-Link are **IsActive** and **Termination Date**. Everything else can be adjusted in Skills Workflow without the next run overwriting it. **Overriding the HR structure** If **Department External Id** and **Typology External Id** are filled in, every imported employee is given that department and typology regardless of what HR-Link sends. This is the setting to use when the agency does not want the full HR structure reproduced in Skills Workflow. --- ### Settings the Agency Controls The integration is configured per company, from the integration settings area in Skills Workflow: | Setting | What it does | | --- | --- | | Token Url | HR-Link service that issues the access token | | Api Key / Api Secret | Credentials used to obtain that token | | Personal Data Url | Feed that supplies the personal data | | Job With Compensation Url | Feed that supplies the job data | | Code | Company code in HR-Link | | Department External Id | Forces a single department on all imported employees | | Typology External Id | Forces a single typology on all imported employees | | User Active Status | Maps the HR-Link status values onto the Skills Workflow active status | | Administrator Mail | Address that receives the error notifications for this company | | Log Level Type | How much detail is written to the integration log | | Log Retention Days | How long the integration log is kept | --- ### What the Agency Needs to Provide - The HR-Link token, personal data and job data service addresses. - A dedicated API key and secret for Skills Workflow. - The company code in HR-Link, and the status values that should count as active. - An administrator e-mail address to receive integration notifications. --- ### Monitoring and Error Handling Every run writes to the integration log inside Skills Workflow, at the level of detail chosen in **Log Level Type**, and the log is kept for the number of days set in **Log Retention Days**. A summary e-mail is sent to the address configured in **Administrator Mail**. A failure on one employee does not stop the run; the remaining employees are still processed and everything that failed is reported at the end. --- ### Good to Know - Employees are matched by their HR-Link identifier. That identifier is what ties the HR record to the Skills Workflow user and should not be edited manually. - Because HR-Link is the source of truth, a person removed from the HR feed will be inactivated in Skills Workflow on the next run. - Departments are matched, not created. A department that exists in HR-Link but not in Skills Workflow needs to be created first, or the override settings used instead. --- ## HubSpot URL: https://documentation.skillsworkflow.com/docs/integrations/HubSpot Summary: HubSpot is where the agency's new business lives — the pipeline of deals, the companies behind them, the value and the expected close date. ### Description This article describes the integration between **HubSpot** and `Skills Workflow`. HubSpot is where the agency's new business lives — the pipeline of deals, the companies behind them, the value and the expected close date. Skills Workflow is where a deal becomes actual work once it is real. This integration carries the deal across the moment it changes, so the commercial team never has to re-create in production what they already built in the CRM. The problem it solves is the hand-off itself. Traditionally, a deal is won and someone forwards the details so a project can be opened — which means a delay, a re-typing, and a project whose value, dates and client details are a snapshot of whatever was in the CRM at the moment of the e-mail. Here the project is created from the deal, and keeps following it: when the deal's value, stage or close date changes in HubSpot, the project changes too. The client is created automatically if the agency has not worked with that company before. --- ### Data Exchange Technology The exchange runs over the HubSpot API, authenticated with a HubSpot private app token. No files and no locally installed application are required. It is **event-driven** — HubSpot notifies Skills Workflow when a deal changes, and Skills Workflow reads the deal back from HubSpot to get its current state before acting. The integration is scoped to **one specific HubSpot pipeline**. Deals in any other pipeline are ignored, so the rest of the CRM's activity does not create projects. The exchange is **one-way**: HubSpot is the source of truth for the deal, and Skills Workflow follows it. --- ### Data Exchange (To Skills Workflow) **Companies → Clients** The first time a deal is seen for a company the agency has not worked with, that company is created as a client, matched on its website so an existing client is reused rather than duplicated. **Deals → Projects** | Received from HubSpot | Becomes in Skills Workflow | | --- | --- | | Deal name | Project name | | Associated company | The client the project belongs to | | Created date | Project start | | Deal stage | The project's stage | | Amount | The project's value | | Expected close date | The agreed date | | Deal type, and the pipeline's own custom fields | Recorded on the project | The first time a deal is seen the project is created and moved to its opening stage; on every later change the same project is updated, rather than a second one being created. --- ### What the Agency Needs to Provide - **A HubSpot private app token** with access to deals, companies and pipelines. - **The pipeline** whose deals should become projects — the integration is deliberately limited to one. - **Webhooks configured in HubSpot** to notify Skills Workflow when a deal changes. - **Agreement on how deal stages map** to project stages. --- ### Monitoring and Error Handling A deal with **no company associated with it** cannot be turned into a project, because there is no client to attach it to. When this happens the integration stops and sends an e-mail alert rather than creating an orphan project — the fix is to associate the company in HubSpot. --- ### Good to Know - **Only one pipeline is integrated.** Deals elsewhere in HubSpot are ignored by design. - **Projects are matched to deals by the HubSpot deal identifier**, so a deal only ever produces one project no matter how often it changes. - **Clients are matched by company website.** A company whose website differs from the existing client record will create a second client. - The integration is one-way: changing the project in Skills Workflow does not update the deal in HubSpot. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | HubSpot-WebhookReceived | Automation | 10 | Active | Entry point: reads the changed HubSpot deal, decides create-client / create-project / update-project | | HubSpot-CreateClient | Automation | 3 | Active | Creates the commercial client from the deal's associated HubSpot company | | HubSpot-CreateProject | Automation | 10 | Active | Creates the Skills Workflow project from the deal and moves it to the "Novo Projecto" (new project) transition | | HubSpot-UpdateProject | Automation | 9 | Active | Updates an existing project's fields and stage from the deal | | HubSpot-ClientExists | Query | 6 | Active | Checks for an existing client by website | | HubSpot-ProjectExists | Query | 6 | Active | Checks for an existing project by HubSpot deal id (custom field `hubspotId`) | | HubSpot-GetProjectDetails | Query | 9 | Active | Resolves company/client ids etc. needed to create a project | | HubSpot-GetProjectUpdateDetails | Query | 6 | Active | Resolves the existing project and its current stage for an update | | HubSpot-GetNovoProjectoTransition | Query | 9 | Active | Looks up the "new project" workflow transition to apply on create | | HubSpot-GetTransitionDetails | Query | 10 | Active | Looks up a workflow transition, used during project creation | Source: `[HubSpot] [Integrations] Webhook Received v10 (Automation) {Active}.json`, `[HubSpot] [Integrations] Create Client v3 (Automation) {Active}.json`, `[HubSpot] [Integrations] Create Project v10 (Automation) {Active}.json`, `[HubSpot] [Integrations] Update Project v9 (Automation) {Active}.json`, `[HubSpot] [Integrations] Client Exists v6 (Query) {Active}.json`, `[HubSpot] [Integrations] Project Exists v6 (Query) {Active}.json`, `[HubSpot] [Integrations] Get Project Details v9 (Query) {Active}.json`, `[HubSpot] [Integrations] Get Project Update Details v6 (Query) {Active}.json`, `[HubSpot] [Integrations] Get Novo Projecto Transition v9 (Query) {Active}.json`, `[HubSpot] [Integrations] Get Transition Details v10 (Query) {Active}.json`. #### How It Works 1. `HubSpot-WebhookReceived` receives a HubSpot webhook payload (a property-change event) and, for the changed deal, calls the HubSpot API to fetch the deal (`GET /deals/v1/deal/{objectId}`). 2. It only continues if the deal's `pipeline` is `15672372` — this integration is scoped to one specific HubSpot pipeline (its stage-name lookup and case name `IsBFerrazDeal`, plus a deal field `produtos_bferraz`, suggest this pipeline belongs to a specific client/brand referred to as "BFerraz" in the export). 3. If the deal has no associated HubSpot company, an email is sent ("... - Deal has no associated Companies") to `helder@skillsworkflow.com` and processing stops. Otherwise it fetches the pipeline's stage list and the associated company (`GET /crm/v3/pipelines/deals/15672372`, `GET /companies/v2/companies/{id}`). 4. `HubSpot-ClientExists` checks for a client by the company's website; if none exists, `HubSpot-CreateClient` is enqueued as background work with the company data (Base64-encoded). 5. The deal is mapped into a normalized object (id, name, company, dates, pipeline/stage, amount, deal type, custom fields like `temperatura`, `tipoDeCampanha`, `tipoDeProposta`, `produtos`), then `HubSpot-ProjectExists` checks for an existing project by the deal id. Depending on the result, either `HubSpot-CreateProject` or `HubSpot-UpdateProject` is enqueued as background work with the mapped deal (Base64-encoded). 6. `HubSpot-CreateProject` builds the project (using `HubSpot-GetProjectDetails`), creates it (`POST /api/Projects`), looks up and applies the "new project" transition (`HubSpot-GetTransitionDetails`, `POST /api/posts`), and sets custom fields (`PUT /api/v3/documentUserFieldValues`). `HubSpot-UpdateProject` follows the same pattern against the existing project (`HubSpot-GetProjectUpdateDetails`, `PATCH /api/projects/{id}` equivalent, `HubSpot-GetNovoProjectoTransition`). #### External System Contact Points - HubSpot API (`api.hubapi.com`): `GET /deals/v1/deal/{id}`, `GET /crm/v3/pipelines/deals/15672372`, `GET /companies/v2/companies/{id}`. Authenticated with a bearer Private App token embedded directly in the automation (see Configuration). - Skills Workflow's own API/analytics: named queries `HubSpot-ClientExists`, `HubSpot-ProjectExists`, `HubSpot-GetProjectDetails`, `HubSpot-GetProjectUpdateDetails`, `HubSpot-GetNovoProjectoTransition`, `HubSpot-GetTransitionDetails`; `POST /api/v3/commercial-clients`, `POST /api/Projects`, `POST /api/posts`, `PUT /api/v3/documentUserFieldValues`. #### Configuration `HubSpot-WebhookReceived` calls the HubSpot API with a hardcoded `Bearer` Private App Access Token in the request headers, rather than a configuration key. The value is not reproduced here. If this export is genuine, treat this HubSpot token as compromised and rotate it. - Pipeline id `15672372` and the "BFerraz" custom fields are hardcoded in the automation rather than configured — this integration is built for one specific HubSpot pipeline/client, not general-purpose. #### Open Questions - What HubSpot subscribes/sends this webhook (a HubSpot workflow, a native webhook subscription) is not part of this export — only the receiving automation is. - What "BFerraz" refers to is not stated in the export beyond appearing in a case name and a custom field name (`produtos_bferraz`). --- ## Integrations URL: https://documentation.skillsworkflow.com/docs/integrations Summary: Skills Workflow connects to the systems an agency already runs — the ERP finance works in, the HR system that owns the people, the proofing tool the creatives… Skills Workflow connects to the systems an agency already runs — the ERP finance works in, the HR system that owns the people, the proofing tool the creatives review in, the storage the files live on — so that each piece of information is maintained in one place and shared everywhere it is needed. This page lists every available integration, what it covers and which way the data flows. --- ### How to Read the Direction Column | Direction | Meaning | | --- | --- | | **In** | The other system is the source of truth; Skills Workflow follows it | | **Out** | Skills Workflow is the source of truth; the other system receives the data | | **Both** | Each system owns part of the exchange — the page explains which | --- ### ERP, Finance & Master Data | Integration | What it covers | Direction | | --- | --- | --- | | [AdnNet](adnet) | Clients and suppliers in; jobs, bills and supplier invoices out | Both | | [AdSolutions](./adsolutions) | Clients, products, suppliers and services in from AdIntegra; jobs and projects out as they leave draft | Both | | [Granatum](./granatum) | Clients, suppliers and products in; approved bills and purchase orders posted out as financial entries | Both | | [Jasmin](./jasmin) | Clients, suppliers and reference data in from Primavera's Jasmin ERP; bills, purchase orders and supplier invoices out (client credit notes built but currently disabled) | Both | | [Kamul](./kamul) | Brands, clients, products and suppliers in; bills and purchase orders out, with status polled back | Both | | [Media360](media360) | Clients and suppliers in; services, projects, contracts, bills, credit notes, supplier invoices and notes out | Both | | [MMS](mms) | Master data load — clients, products, suppliers, services and users | In | | [Omie](./omie) | Clients out to Omie daily; bills out as service orders, with the issued NFS-e invoice read back | Both | | [Primavera](./primavera) | Financial master data in; bills, credit notes, expenses, purchase orders, supplier invoices and notes out | Both | | [Publi](./publi) | An approved media estimate sent out to Publi as an "orçamento" | Out | | [Sage](./sage) | Financial master data in; bills, credit notes, expenses, purchase orders, supplier invoices and notes out | Both | | [TOConline](toconline) | Approved bills, client credit notes and supplier invoices issued in TOConline, with the document number written back; clients, suppliers, services and taxes kept in sync | Both | | [VBD](vbd) | Skills Workflow polls an external VBD feed and creates clients/projects from it | In | | [VBS](vbs) | Full commercial and financial cycle, with each flow switchable per company | Both | | [WK Radar](./wk-radar) | Clients, suppliers and services in; bills and supplier invoices out (bill hand-off currently disabled) | Both | | [iSAP](./isap) | Employees, clients and products in; jobs both ways, including closure | Both | --- ### Job & Production Management | Integration | What it covers | Direction | | --- | --- | --- | | [7Log](./7log) | Jobs from 7Log created/updated as projects, on a 15-minute poll | In | | [Active Collab](./active-collab) | ActiveCollab tasks mirrored as jobs — creation, updates, stage, comments and attachments | In | | [Automations — Generic Create Project](./automations) | A generic, credential-protected inbound endpoint any system can call to create a project | In | | [Azure DevOps](./azure-devops) | Creates an Azure DevOps work item for a deliverable and keeps its status synced to the job's stage | Out | | [CETA](./ceta) | Clients, products and approved timesheets out; projects and jobs in | Both | | [Client and Agencies](./client-and-agencies) | Job/project/comment sync between an agency's Skills Workflow tenant and its client's — both halves | Both | | [HubSpot](./hubspot) | Won/updated HubSpot deals (one pipeline) become and stay in sync as projects | In | | [JAM](./jam) | Clients, products, projects and jobs out; status changes, assignments and files in | Both | | [Visto](./visto) | Print-production stage sync with Visto — inbound stage updates; outbound side delivered via [Zappier](./zappier) | Both | | [WMS](./wms) | Two-way job/project/brief/comment/assignment/product sync with an external Work Management System | Both | | [Zappier](./zappier) | Delivers Visto job/stage-change payloads via a Zapier webhook — the outbound half of [Visto](./visto) | Out | --- ### HR & People | Integration | What it covers | Direction | | --- | --- | --- | | [ADP](adp) | Employee provisioning from ADP payroll files | In | | [BambooHR](bamboo) | Employees and time off, from three independent daily-scheduled automations (only the employee-update one currently runs — see the page) | In | | [CS](cs) | Employee provisioning and terminations from Career Settings | In | | [EAS](./eas) | Users, leaves, timesheets, clients, products and job jackets | Both | | [HR-Link](hr-link) | Employee provisioning from HR-Link personal and job data | In | | [Reach](./reach) | User provisioning from SAP SuccessFactors | In | | [UtilPro](./utilpro) | Employee provisioning, including working-time rules | In | | [Workday Informatica](./workday-informatica) | Absences and leave periods from Workday (VML), synced daily / every 6 hours | In | --- ### Time & Timesheets | Integration | What it covers | Direction | | --- | --- | --- | | [VBS Timesheet](vbs-timesheet) | Time and leave out to VBS, with status read back; also includes a client-specific cost-centre export view | Both | | [GSP Timesheet Importer](gsp-dynamic-timesheet-importer) | Dynamics timesheet report loaded for reporting | In | | [Timely](./timely) | Clients/projects/assignments/work types synced with Timely; hours logged in Timely become timesheets (two parallel sync mechanisms exist — see the page) | Both | --- ### Creative & Collaboration | Integration | What it covers | Direction | | --- | --- | --- | | [ZiFlow](ziflow) | Proof decisions move the deliverable's stage; proofs can also be created, viewed and managed from Skills Workflow | Both | | [Microsoft Teams](microsoft-teams) | Posts a card to a Teams channel on any configured event | Out | | [Cloud Storage](cloud-storage/box) | Box, Google Drive and SharePoint — folders, uploads and previews (client folder auto-creation currently disabled) | Both | | [Sitecore](./sitecore) | Order-brief submission panel plus an asset-library panel closely related to [Swivle](./swivle) | Both | | [Swivle](./swivle) | Asset-library search/browse/cart panel embedded in a Request | In | | [Siphon](./siphon) | Forwards an approved brief's data to an external webhook, likely to create a Swivle shared link | Out | --- ### Identity & Access | Integration | What it covers | Direction | | --- | --- | --- | | [Single Sign-On](./single-sign-on-sso) | SAML 2.0 authentication via Google Suite, Microsoft Entra or Okta | — | | [Azure AD Blocker](azure-ad-blocker) | Blocks Azure AD accounts for users delinquent on timesheets, and unblocks them on request | Out | --- ### Reporting & Data | Integration | What it covers | Direction | | --- | --- | --- | | [Power BI](powerbi) | Scheduled query exports as Power BI data sources | Out | | [Google Data Studio](google-data-studio) | Data extraction queries loaded into Google BigQuery for reporting in Google Data Studio (Looker Studio) | Out | | [Custom Table Importer](custom-table-importer) | Excel files loaded into custom tables | In | | [API](api) | The Skills Workflow Integration API and Client API | Both | --- ### Cross-References Some components and connections span more than one integration page in this list: | Components | Where documented | What links them | | --- | --- | --- | | `Client and Agencies (Agency)` module ↔ `Client and Agencies (Client)` module | [Client and Agencies](./client-and-agencies) | Two Skills Workflow tenants (an agency's and its client's) calling each other's integration-workflow endpoints to keep jobs/projects/comments in sync. Shipped as two Marketplace packages, documented as one integration. | | `WMS (Server)` module ↔ `WMS (Client)` module | [WMS](./wms) | Two halves of one bridge to a Work Management System, sharing the same `x-shared-secret` webhook credential. Shipped as two Marketplace packages, documented as one integration. | | `Visto` module ↔ `Zappier` module | [Visto](./visto), [Zappier](./zappier) | The `Zappier` Marketplace package's components are internally named `Visto-StageChanged` / `Visto-JobStageUpdate-Get` / `Visto-JobById-Get` — despite the package name, it's the outbound half of the Visto integration, delivering job/stage data to Visto via a Zapier catch-hook. | | `Sitecore` module ↔ `Swivle` module | [Sitecore](./sitecore), [Swivle](./swivle) | Both modules' `Content Library` Workspaces call the same underlying integration-workflow automations (asset search, filters) for what looks like the same DAM — variable naming inside one of them (`zonzaResult`) is a lead that the real system behind it is Zonza; see the note on [Zonza](zonza). | | `Box` module ↔ `Ziflow` module | [Cloud Storage — Box](cloud-storage/box), [ZiFlow](ziflow) | `Box - Ziflow - Create temporary shared link` creates temporary Box file links used to feed previews into ZiFlow proofs. | | `SQL Server` module | [VBD](vbd) | Every component in the Marketplace export's `SQL Server` module is internally named `VBD - ...`; it's documented under the existing VBD page, whose direction has been corrected from "Skills Workflow publishes" to "Skills Workflow polls an external VBD feed" based on the export. | | `AdSolutions` vs `AdnNet` | [AdSolutions](./adsolutions), [AdnNet](adnet) | **Not the same integration**, despite the similar name — `AdSolutions` connects to "AdIntegra" (a different external system); noted here only to prevent the two being confused. | --- ### Product Pages and Technical References Every integration has a **product page** — this is what the tables above link to. It explains what the integration takes care of, what the agency has to provide, and what can be configured. Most pages also include a **Technical Reference** section (or, for a few, a separate Technical Reference page) — the interface specification: components, data flow, external endpoints and configuration. It is written for the team implementing or troubleshooting the exchange, and is not needed to understand or configure the integration. --- ## iSAP URL: https://documentation.skillsworkflow.com/docs/integrations/isap Summary: iSAP is the agency's SAP-based back office. ### Description This article describes the integration between **iSAP** and `Skills Workflow`. iSAP is the agency's SAP-based back office. This integration keeps the two systems working from the same book of record: the people, clients and products that finance and administration maintain in iSAP appear in Skills Workflow automatically, and the jobs the teams open in Skills Workflow flow back into iSAP for costing and billing. The job flow works in **both directions**, which is what makes this integration different from a simple master-data feed. A job can start life in either system and still end up correctly represented in the other, with the two staying in step through its whole life — including when it is closed. For the day-to-day detail of how jobs behave once the integration is in place, see **[Job Maintenance](job-maintenance)**. --- ### Data Exchange Technology Data moves as **text files over FTP**, using two separate connections: | Connection | Direction | What travels on it | | --- | --- | --- | | Send | Skills Workflow → iSAP | Jobs | | Receive | iSAP → Skills Workflow | Employees, Clients and Products, Jobs | Having a distinct send and receive server means the agency can keep the inbound and outbound exchanges on different infrastructure, with different credentials, rather than sharing one folder for both. Files follow a fixed naming convention built from the company code, a two-letter content code and a sequence number: | File | Contents | | --- | --- | | `OE.TXT` | Employees | | `OC.TXT` | Clients and products | | `OJ.TXT` | Jobs | The sequence number determines processing order, so files are always applied in the order iSAP produced them, even if several are waiting. Once a file has been handled it is moved into a **Success** or a **Failure** subfolder, so it is never processed twice and the agency can see what happened to any given delivery. The integration runs on a schedule, company by company. --- ### Data Exchange (To Skills Workflow) **Employees** Employee records from iSAP are created and maintained as Users and Employees in Skills Workflow, carrying their employee identifier, initials, first and last name, department, title, organisational element, phone, e-mail, status and effective start date. The file also flags each person's role in the commercial structure — **Account Manager**, **Account Executive** and **Buyer**. Those flags matter beyond the user record: a job can only be exported to iSAP if its Project Owner and Job Creator are marked as AM/AE, so this feed is what makes the outbound job flow possible. Departments and typologies are created when they do not already exist. **Clients and Products** The client and product catalogue is imported from iSAP, with codes, account group, local and English names, addresses, country, postal and zip codes, phone, parent reference, payment methods and payment terms. **Jobs** Jobs opened in iSAP are imported into Skills Workflow, creating the project and the job. Jobs closed in iSAP are closed in Skills Workflow, and the job's end date is set to the day it was closed. --- ### Data Exchange (From Skills Workflow) **Jobs** Jobs created in Skills Workflow are written to a job file and sent to iSAP. Every subsequent change to the job is sent as well, so iSAP always holds the current version. The export is optional and is switched on per company with the **Export Job** setting. It can also be limited to jobs explicitly marked for integration, rather than every job, using **Send Only To Integrate** — useful when only part of the agency's work is meant to reach the back office. --- ### Settings the Agency Controls The integration is configured per company, from the integration settings area in Skills Workflow: | Setting | What it does | | --- | --- | | Send FTP Host / Port / Username / Password / Directory | The connection jobs are sent on | | Receive FTP Host / Port / Username / Password / Directory | The connection files are collected from | | Export Job | Whether jobs are sent to iSAP at all | | Send Only To Integrate | Limits the export to jobs marked for integration | | Job File Sequence | The sequence number the next outbound job file will use | | Project Open Workflow State Name | The stage a project is placed in when opened | | Project Close Workflow State Name | The stage that represents a closed project | | Job Open Workflow State Name | The stage a job is placed in when opened | | Job Close Workflow State Name | The stage — or stages, separated by `;` — that represent a closed job | | Account Executive Id | The field that identifies the Account Executive | | Account Manager Id | The field that identifies the Account Manager | | Leave Responsibles | Users, separated by `;`, whose responsible assignment the integration must not change | | End Date Days | How far ahead a job's end date may be set | | Continue On First Error | Whether a failing record stops the file or the run continues | | Administrator Mail | Address that receives the error notifications for this company | | Log Level Type | How much detail is written to the integration log | The workflow state settings are what let each agency map its own stage names onto the open and closed concepts iSAP expects, instead of being forced into fixed stage names. --- ### What the Agency Needs to Provide - Two FTP endpoints — one to send to, one to collect from — with directories and credentials for each. - The iSAP exports delivered into the receive directory, following the file naming convention above. - The company code used in iSAP. - Confirmation of which workflow stages count as open and closed for projects and for jobs. - Confirmation of which user fields carry the Account Manager and Account Executive. - An administrator e-mail address to receive integration notifications. --- ### Monitoring and Error Handling Every run writes to the integration log inside Skills Workflow, at the level of detail chosen in **Log Level Type**. The log is cleared at the start of each run. A summary e-mail is sent to the address configured in **Administrator Mail**. Whether a failing record aborts the rest of the file is the agency's choice, through **Continue On First Error** — strict processing suits a first rollout, where a bad record should stop everything and be investigated; permissive processing suits steady state, where one malformed row should not hold up the day's work. A file that could not be fully imported is moved to the **Failure** folder and can be re-delivered once the underlying issue is resolved. --- ### Good to Know - A job will not export if its Project Owner and Job Creator are not marked as Account Manager / Account Executive in iSAP. This is the most common cause of integration errors on this interface. - iSAP is the source of truth for employees, clients and products. Manual changes to those records in Skills Workflow will be overwritten. - Jobs are shared. Either system can open one, and closing it on either side closes it on the other. - **Job File Sequence** is part of the contract with iSAP. Changing it manually will make the files arrive out of order. --- ## JAM URL: https://documentation.skillsworkflow.com/docs/integrations/jam Summary: JAM is the agency's job administration system. ### Description This article describes the integration between **JAM** and `Skills Workflow`. JAM is the agency's job administration system. This integration makes Skills Workflow the place where the commercial structure is maintained, and JAM the place where the administrative side of the job lives — with the two kept in step automatically. The clearest consequence for the agency: **client and product maintenance is switched off in JAM once the integration is enabled**. There is exactly one place to create a client, and it is Skills Workflow. That removes the most common source of mismatched records between the two systems. --- ### Data Exchange Technology The exchange runs over **REST services**, using the Skills Workflow Integration API. Requests are authenticated with credentials issued by the Skills Workflow team. Calls can optionally be made *on behalf of* a specific user, so that an action arriving from JAM is attributed to the right person in Skills Workflow and respects their permissions — rather than everything appearing to come from a generic integration account. --- ### What Goes Out To JAM | Sent to JAM | Known in JAM as | Notes | | --- | --- | --- | | Clients | *Anunciante* | Created and updated automatically from Skills Workflow | | Products | *Produto* | Created with their client, name and code | | Projects | *Campanha* | Sent automatically on creation | | Jobs | — | Sent when the job changes status in Skills Workflow | **How jobs are triggered.** Jobs are not sent on a timer. They are exported when a job moves between statuses in Skills Workflow and that transition is configured with the **SendToExternal** action. This means the agency controls exactly which stage changes push a job to JAM, by configuring the workflow rather than by asking for a code change. --- ### What Comes Into Skills Workflow | Received from JAM | Notes | | --- | --- | | Job status changes | A status change in JAM moves the job in Skills Workflow, and can post a comment against it | | Team assignments | People can be added to or removed from the job team | | Files | Uploaded into the job feed in Skills Workflow, so the conversation and the assets stay together | | Dates | The requested date can be updated | --- ### What the Agency Needs to Provide - Network access between JAM and Skills Workflow. - Confirmation of which workflow transitions should carry the **SendToExternal** action. - Agreement on the status codes used on both sides, so a status change in one system maps to the right stage in the other. Skills Workflow issues the API credentials. --- ### Good to Know - Clients and products cannot be edited in JAM while the integration is enabled — those modules are disabled by design. - Projects and jobs are created in Skills Workflow. JAM changes their status and content; it does not create them. - Because job export is driven by workflow transitions, adding a new stage to the workflow does not automatically export from it — the action has to be configured on that transition. --- For the API calls, payloads and field mappings, see the **[Technical Reference](./reference)**. --- ## JAM — Technical Reference URL: https://documentation.skillsworkflow.com/docs/integrations/jam/reference Summary: There was a need to exchange data between JAM and Skills Workflow --- Service REST. This page is the interface specification for the JAM integration — file formats, naming conventions and field-by-field mappings. It is written for the team implementing the exchange. For what this integration does and how it is configured, see **[JAM](./)**. ### Description There was a need to exchange data between JAM and Skills Workflow --- ### Data Exchange Technology Service REST. The scope of data exchanged on this integration includes: - OAuth - Master data - Clients & Products - From Skills Workflow to JAM - Projects & Jobs - From Skills Workflow to JAM - From JAM to Skills Workflow - Files - From Skills Workflow to JAM - From JAM to Skills Workflow - Uploaded into Skills Workflow's job feed --- ### Data Exchange This section describes the Data exchanged between systems. Please see below the data exchanged. #### Skills Workflow Integration API To use any endpoint from the Skills Workflow Integration API, it is necessary to pass the following Headers: - X-AppSecret -Provided by Skills Workflow team - X-AppId -Provided by Skills Workflow team - X-AppUser - Not mandatory - Use this parameter to impersonate by passing the Skills Workflow's UserId - See how to get UserId by User's ExternalId on the Jobs tab, step 1. - It will have in consideration user permissions and post as being the user Clients are managed in Skills Workflow. - New clients created in Skills Workflow are automatically created in JAM. - Any change in the client data is also synched with JAM. - The client is known as "Anunciante" - In JAM it is only mandatory the client name It is not possible to edit Client data in JAM since it must be done in Skills Workflow. This module in JAM is disabled when the integration with Skills Workflow is enabled. #### Client Data Exchanged Work in Progress Mappings ``` Work in Progress ``` Products are managed in Skills Workflow. - New products created in Skills Workflow are automatically created in JAM. - Any change in the product data is also synched with JAM. T- he product is known as "Produto" - To create a new product it is mandatory to send the client code, product name and product code It is not possible to edit Product data in JAM since it must be done in Skills Workflow. This module in JAM is disabled when the integration with Skills Workflow is enabled. #### Product Data Exchanged Work in Progress Template ``` Work in Progress ``` Projects are managed in Skills Workflow. - New projects created in Skills Workflow are automatically sent to JAM. - The project is known as "Campanha" - To create a new job it is mandatory to send the Project #### Project Data Exchanged Work in Progress Template ``` Work in Progress ``` Jobs are created in Skills Workflow and sent to JAM. - The jobs will be sent to JAM when a status transition is done in Skills Workflow. - In Skills Workflow it is possible to configure certain actions when the jobs are moved between status. - If the action "SendToExternal" is configured in that transition, jobs will be exported to JAM. #### Change Job Status in Skills Workflow To change the job status it is necessary to pass: - UserEmail- The user email that changed the status in JAM - DocumentTypeName - The document type - "Skill.Module.BusinessObjects.Deliverable" - JobNumber- The job number - IsVisibleToClient - Send as "True" - Text - The post description - Action - List of actions, in this case, the action to be used is Transition - Transition - Mandatory to pass the - ExternalId - The status external code to which the job should go - Assignments - userEmail - User email to add to team or remove from team - assign - To add user to team send "true", to remove user from team send "false" - Files - fileLink- The link to open the file. - fileName - The file name to be shown - Dates - requestedDate - Date must be with format 2020-03-23T12:03:21 Please check below how to get each field. #### Steps to change the job's status 1. Change Job Status, Assign users, Add Links ``` POST /api/posts Host: integration-api-skills-dev-we.azurewebsites.net Content-Type: application/json X-AppId: {{X-AppId}} X-AppSecret: {{X-AppSecret}} { "companyCode": "{companyCode}", "userEmail": "{userEmail}", "documentTypeName": "Deliverable", "documentNumber": "{jobNumber}", "isVisibleToClient": true, "Text": "{text}" "actions": { "transition": { "externalId": "{externalId}" } }, "assignments": [ { "userEmail": "{userEmail}", "assignmentTypeName": "Executor", "assign": true }, { "userEmail": "{userEmail}", "assignmentTypeName": "Executor", "assign": false } ], "files": [ { "name": "{fileName}", "link": "{fileLink}", "isTemp": true, "isFlagged": false }, { "name": "{fileName}", "link": "{fileLink}", "isTemp": true, "isFlagged": false } ], "Dates": { "RequestedDateUtc": "{requestedDate}" } } } ``` 2. Update JobStatusCode ``` PUT /api/documentUserFieldValues Host: integration-api-skills-dev-we.azurewebsites.net Content-Type: application/json X-AppId: {{X-AppId}} X-AppSecret: {{X-AppSecret}} { "documentTypeName": "Deliverable", "documentId": "{jobId}", "documentUserFieldValues": [ { "columnName": "JamStatusCode", "value": "{JamStatusCode}" } ] } ``` #### Files Work in Progress #### Files Data Exchange Work in Progress #### Template ``` Work in Progress ``` #### Conclusion The contents of this document create the foundation for data and process communication methodology between Skills Workflow and Agencies. The current known data and process transfers are contained in this document but more may be created as additional data and process needs are discovered. --- ## Jasmin URL: https://documentation.skillsworkflow.com/docs/integrations/Jasmin Summary: Jasmin is Primavera BSS's cloud accounting platform — the agency's ERP, where the books are kept and where invoices, credit notes and purchase documents are… ### Description This article describes the integration between **Jasmin** and `Skills Workflow`. Jasmin is Primavera BSS's cloud accounting platform — the agency's ERP, where the books are kept and where invoices, credit notes and purchase documents are legally issued. Skills Workflow is where the work those documents are for is planned, delivered and approved. This is one of the widest financial integrations in the platform. It covers the full document cycle in both directions, so the operational teams work in Skills Workflow and finance keeps working in Jasmin, with neither side retyping the other's data. In practice it takes care of two jobs: - **Bringing the accounting foundation in** — clients, suppliers, currencies, payment terms, taxes, countries, sales items and purchase items are pulled from Jasmin, so that everything raised in Skills Workflow uses the same codes finance will post against. - **Issuing the documents out** — approved bills, purchase orders and supplier invoices are created in Jasmin, and the reference Jasmin assigns is written back onto the Skills Workflow document. That last point is what makes the cycle auditable: from any document in Skills Workflow, anyone can see exactly which Jasmin document it produced, without opening the ERP. --- ### Data Exchange Technology The exchange runs over the Jasmin web API. Skills Workflow authenticates with the agency's own application credentials and then calls Jasmin directly. No files and no locally installed application are required. The integration is **multi-company aware**: a Skills Workflow company maps to a particular Jasmin account and subscription, so a group running several companies can post each one's documents into its own set of books. The two directions work differently: - **Clients and suppliers are pulled daily**, picking up whatever was created in Jasmin since the previous day. - **The remaining reference data** (countries, currencies, payment terms, taxes, sales and purchase items, credit-note reasons) is refreshed on demand. - **Documents are issued as they are approved**, event-driven, not on a schedule. --- ### Data Exchange (To Skills Workflow) | Received from Jasmin | Becomes in Skills Workflow | | --- | --- | | Customers | Billing clients and commercial clients, with their company link | | Suppliers | Suppliers | | Countries, currencies, payment terms | The matching reference records | | Taxes | VAT rates | | Sales items | Services | | Purchase items | Expense item types | | Memo reasons | Credit-note reversal reasons | --- ### Data Exchange (From Skills Workflow) | Document | Sent to Jasmin as | When | | --- | --- | --- | | **Bill** | Invoice | The bill moves from *Under Approval* to *Integrada* | | **Supplier Invoice** | Purchase invoice | The supplier invoice moves from *Novo* to *Integrado* | | **Purchase Order** | Purchase order | The purchase order is created | | **Client Credit Note** | Credit memo | *Currently switched off — see below* | Every document is confirmed by reading it back from Jasmin after it is created, and the resulting reference is stored on the Skills Workflow document. The credit-note flow is fully built, but the trigger that fires it is switched off in this configuration, so approved client credit notes do not reach Jasmin today. Everything else is unaffected. --- ### What the Agency Needs to Provide - **A Jasmin subscription with API access**, plus the application credentials for Skills Workflow to authenticate with. - **The Jasmin account and subscription** each Skills Workflow company should post into. - **The approval stages** listed above on the Bill and Supplier Invoice document types, since reaching them is what issues the document. --- ### Good to Know - **Documents are only issued once they have cleared approval.** Moving a document between other stages never issues it by accident. - **The reference data has to come in before documents go out** — a bill can only be issued against clients, taxes and items that Jasmin already knows. - **Each company posts into its own Jasmin books**, so the same tenant can serve several legal entities. - The integration is one-way per document: changing an invoice in Jasmin does not update the bill in Skills Workflow. --- ### Technical Reference #### Components | Flow | Webhook | Automation | Key Queries | | --- | --- | --- | --- | | Bill → Invoice | Jasmin-OnInvoiceStageUpdated (v3, Active) | Jasmin-Integrate Invoice (v14) | Jasmin-GetBill, Jasmin-GetBillItems | | Client Credit Note | Jasmin-OnCreditNoteCreated (v4, **Disabled**) | Jasmin-IntegrateCreditNote (v9) | Jasmin-GetCreditNote, -Items | | Supplier Invoice | Jasmin-OnSupplierInvoiceUpdated (v1, Active) | Jasmin-Integrate Supplier Invoice (v4) | Jasmin-GetSupplierInvoice, -Items | | Purchase Order | Jasmin-OnPurchaseOrderCreated (v3, Active) | Jasmin-Integrate Purchase Order (v4) | Jasmin-GetPurchaseOrder, -Items | | Master data | Trigger | Automation | Key Queries | | --- | --- | --- | --- | | Customers | Daily | Jasmin - Customers (v6) | Jasmin-GetCompanies, -GetBillingClient, -GetCommercialClient, -GetClient | | Suppliers | Daily | Jasmin - Suppliers (v8) | Jasmin-GetSuppliers | | Countries | On demand | Jasmin - Countries (v2) | — | | Currencies / Payment Conditions / Taxes | On demand | Jasmin- Currency PaymentCondition Tax (v5) | Jasmin-GetCurrencies, -GetPaymentConditions, -GetTaxes | | Sales Items (services) | On demand | Jasmin - SalesItems (v4) | Jasmin-GetSalesItems | | Purchase Items (expense types) | On demand | Jasmin - PurchaseItems (v2) | Jasmin-GetPurchaseItems, custom table `JasminTaxSchema` | | Reversal Reasons | On demand | Jasmin - ReversalReason (v2) | Jasmin-GetMemoReasons | Plus **setup/plumbing**: `Jasmin - Initial Configuration` (creates the custom fields this package needs, `POST /api/v3/document-user-fields`), `Jasmin-CreateTaxSchemaCustomTable` (creates the `JasminTaxSchema` custom table), `Jasmin-OauthClientCredentials` (shared OAuth2 client-credentials token helper), `Jasmin-WebhookEndpoint` and `Jasmin - Webhook Received` (a no-op stub and a generic event-type dispatcher respectively — neither is wired to a webhook in this export), and named query `Jasmin-DocumentsNotSettled` (lists bills/expenses/supplier invoices not yet settled — not called by any exported automation). Source: files under `[Jasmin] [Integrations] ...` in the Marketplace export (43 files, 42 distinct components after de-duplicating one attachment pair). `Jasmin-OnCreditNoteCreated` is exported with `"active": false` — its target automation, `Jasmin-IntegrateCreditNote`, exists and is Active, but nothing currently triggers it (confirmed: the webhook's `automationId` matches `Jasmin-IntegrateCreditNote`'s own id exactly). As exported, client credit notes are not sent to Jasmin. #### How It Works Every Jasmin-calling automation gets an OAuth2 client-credentials token first (`POST https://identity.primaverabss.com/connect/token`) before calling the Jasmin API at `{Config.host}/{account}/{subscription}/...` (account/subscription resolved per-document from the query results, since a company can map to a different Jasmin account/subscription). **Financial documents** (all four follow the same shape): the webhook fires on the approval transition (Bill: Under Approval → "Integrada"; Supplier Invoice: "Novo" → "Integrado"; Credit Note and Purchase Order: on creation) and calls the matching `Jasmin-Integrate ...` automation, which builds the document + line items from two named queries, `POST`s it to the relevant Jasmin endpoint (`billing/invoices`, `billing/memos`, `invoiceReceipt/invoices`, `purchases/orders`), re-fetches it by the returned id to confirm, and patches the Skills Workflow document with the Jasmin reference (`PATCH /api/bills/{id}`, `/api/client-credit-notes/{id}`, `/api/supplier-invoices/{id}`, `/api/purchase-orders/{id}`). **Master data**: `Jasmin - Customers` and `Jasmin - Suppliers` run daily, pulling everything created since yesterday from Jasmin (`salesCore/customerParties/odata`, `purchasesCore/supplierParties/odata`, both `$filter`ed by `CreatedOn` and iterated per company via `Jasmin-GetCompanies`), resolving and creating/updating the matching billing client, commercial client (+ company link) or supplier. The remaining master-data automations (`Countries`, `Currency PaymentCondition Tax`, `SalesItems`, `PurchaseItems`, `ReversalReason`) are on-demand pulls of Jasmin reference data (`corePatterns/countries`, `corePatterns/currencies`, `financialCore/paymentTerms`, `taxesCore/taxTypeCodes`, `salesCore/salesItems`, `purchasesCore/purchasesItems`, `logisticsCore/memoReasons`, all via OData), each resolved and created in Skills Workflow (`/api/v3/countries`, `/api/v3/currencies`, `/api/v3/payment-conditions`, `/api/vats`, `/api/v3/services`, `/api/expense-item-types`, `/api/reversal-reasons`). #### External System Contact Points - Jasmin identity: `POST https://identity.primaverabss.com/connect/token` (OAuth2 client credentials). - Jasmin API (`{Config.host}/{account}/{subscription}/...`): `salesCore/customerParties/odata`, `purchasesCore/supplierParties/odata`, `corePatterns/countries/odata`, `corePatterns/currencies/odata`, `financialCore/paymentTerms/odata`, `taxesCore/taxTypeCodes/odata`, `salesCore/salesItems/odata`, `purchasesCore/purchasesItems/odata`, `taxesCore/itemTaxSchemas/{id}`, `logisticsCore/memoReasons/odata`, `billing/invoices`, `billing/memos`, `invoiceReceipt/invoices`, `purchases/orders`. - Skills Workflow's own API/analytics: the named queries listed above; `POST /api/v3/billing-clients`, `/api/v3/commercial-clients`, `/api/v3/commercial-client-companies`, `/api/v3/suppliers`, `/api/v3/countries`, `/api/v3/currencies`, `/api/v3/payment-conditions`, `/api/vats`, `/api/v3/services`, `/api/expense-item-types`, `/api/reversal-reasons`, `/api/v3/document-user-fields`, `/api/v3/custom-tables/...`. #### Configuration - A `Config` configuration key — holds Jasmin's `host` and OAuth client credentials. Values are not part of the export. - Custom table **`JasminTaxSchema`** — caches Jasmin tax-schema lookups used when resolving purchase item taxes. #### Open Questions - Whether disabling the Credit Note webhook was intentional (e.g. credit notes are handled another way) or an oversight is not determinable from the export. - `Jasmin-WebhookEndpoint` is a no-op (Start → Exit with nothing in between) and `Jasmin - Webhook Received` is a generic dispatcher — neither has a matching webhook file in this export, so what (if anything) currently calls them isn't determinable. - `Jasmin-DocumentsNotSettled` isn't called by any exported automation. --- ## Job Maintenance URL: https://documentation.skillsworkflow.com/docs/integrations/isap/job-maintenance Summary: For what the iSAP integration covers overall — employees, clients, products and the job exchange — see iSAP. This article describes how the job maintenance is done in Skills Workflow when there is an interface with iSAP in place. For what the iSAP integration covers overall — employees, clients, products and the job exchange — see **[iSAP](./)**. --- ### Job Creation in Skills Workflow After a Job is created in Skills Workflow, it will automatically flow to iSAP. Every time a job is modified it will update the information in iSAP. Once complete, the job needs to be closed in iSAP. --- ### Job Creation in iSAP After a Job is created in iSAP, it will automatically create a new project and job in Skills Workflow. The job fields that synch with iSAP are (SW vs iSAP names): - Number - Job Title - Title - Job Description (the first 40 characters) - Description - all the characters are added to the jobs' description in Skills Workflow - Company - Job Type - Client Code - Product Code - Department - Cost Center - Start Date - Estimated Start Date - End Date - Estimated EndDate - Active Flag - The Account Executive and Account Manager are included in the job's export - Account Manager is the Project Owner - Account Executive is the Job creator - In order for a job to be exported to iSAP, the Project Owner and Job Creator needs to be marked as AM/AE in iSAP, otherwise it will generate integration errors. Every time a job is modified in the system, it is sent to iSAP. - Integration synchs the modified jobs once every hour - Any change applied to the following fields in the Job's Info tab will mark the job to be sent to iSAP: - Title - Dates - When a job is closed in iSAP it will also be closed in Skills Workflow - Additionally, the job's end date is updated in SW according to the day it was closed - On iSAP side, the date will not be synched unless the job is modified after being closed - The closing state is defined in the integration settings --- ## Kamul URL: https://documentation.skillsworkflow.com/docs/integrations/Kamul Summary: Kamul is the agency's ERP — where the client and supplier ledgers are kept and where invoices and purchase orders are processed. ### Description This article describes the integration between **Kamul** and `Skills Workflow`. Kamul is the agency's ERP — where the client and supplier ledgers are kept and where invoices and purchase orders are processed. Skills Workflow is where the work is run and the documents originate. The integration keeps the two aligned so that the commercial teams work in Skills Workflow and finance keeps working in Kamul, without anyone maintaining the same brand, client, product or supplier list twice. It takes care of two jobs: - **Bringing the master data in** — brands, clients, products and suppliers registered in Kamul are created and kept up to date in Skills Workflow every day. - **Sending the documents out** — bills and purchase orders are submitted to Kamul, and the reference Kamul assigns is written back onto the document. It also does something the other financial integrations do not: because Kamul does not always answer immediately, the integration **keeps checking back** on documents it has submitted but not yet had a decision on, and updates them once Kamul has processed them. Nothing is left in limbo waiting for someone to notice. --- ### Data Exchange Technology The exchange runs over the Kamul web API, using addresses and credentials configured by the agency. No files and no locally installed application are required. The integration runs on a **daily schedule** for the master data. A single scheduled run drives all four pulls in sequence — brands, clients, products and suppliers — each picking up what changed since the previous day. Documents are submitted **as they become ready**, and the follow-up check on pending documents runs separately. --- ### Data Exchange (To Skills Workflow) | Received from Kamul | Becomes in Skills Workflow | | --- | --- | | Brands | Brands | | Clients | Commercial clients and billing clients, with their company link | | Products | Commercial and billing products, with their company link | | Suppliers | Suppliers | New clients are also moved to their correct opening stage as they are created, so they arrive usable rather than in draft. --- ### Data Exchange (From Skills Workflow) | Document | Sent to Kamul as | | --- | --- | | **Bill** | Invoice (*factura*) | | **Purchase Order** | Purchase order (*orden de compra*) | Each submitted document carries a Kamul reference from then on. Documents still awaiting a response are re-checked against Kamul and updated once a decision exists. --- ### What the Agency Needs to Provide - **A Kamul account with API access**, plus the address and credentials for Skills Workflow. - **Confirmation of the opening stage** new clients should be moved to as they are imported. - **The document types** in Skills Workflow that correspond to bills and purchase orders for export. --- ### Good to Know - **The master data refresh runs once a day**, so a client or supplier created in Kamul appears in Skills Workflow the following run rather than immediately. - **Records are matched by their Kamul identifier**, stored on the Skills Workflow record. - **Submitted documents are not fire-and-forget** — the pending check is what closes the loop, so a document with no reference yet is not necessarily lost. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Kamul-Integration Schedule | Automation | 2 | Active | Daily: enqueues the Brands/Clients/Products/Suppliers refreshes | | Kamul-Brands | Automation | 2 | Active (own scheduler disabled — see below) | Pulls brands changed in Kamul | | Kamul-Clients | Automation | 3 | Active (own scheduler disabled — see below) | Pulls clients changed in Kamul, and transitions new ones to the right stage | | Kamul-Products | Automation | 3 | Active (own scheduler disabled — see below) | Pulls products changed in Kamul | | Kamul-Suppliers | Automation | 3 | Active (own scheduler disabled — see below) | Pulls suppliers changed in Kamul | | Kamul-Bill | Automation | 3 | Active | Sends a bill to Kamul as an invoice ("factura") | | Kamul-PurchaseOrder | Automation | 2 | Active | Sends a purchase order to Kamul ("ordencompra") | | Kamul-UpdatePendingDocuments | Automation | 1 | Active | Checks Kamul for the status of bills/purchase orders still pending and patches them | | Kamul-GetBrand, Kamul-GetClient, Kamul-GetProduct, Kamul-GetSupplier | Query | 1–3 | Active | Resolve existing records for each master-data sync | | Kamul-GetClientTransitionByName | Query | 1 | Active | Resolves the workflow transition to apply to a newly created client | | Kamul-GetStageByName | Query | 1 | Active | Resolves a workflow stage by name — not called by any automation in this export | | Kamul-BillById | Query | 5 | Active | Builds the outbound payload for a bill | | Kamul-PurchaseOrderById | Query | 2 | Active | Builds the outbound payload for a purchase order | | Kamul-DocumentsPending | Query | 1 | Active | Lists bills/purchase orders still awaiting a Kamul response | Source: `[Kamul] [Integrations] Integration Schedule v2 (Automation) {Active}.json`, `[Kamul] [Integrations] Brands v2 (Automation) {Active}.json`, `[Kamul] [Integrations] Clients v3 (Automation) {Active}.json`, `[Kamul] [Integrations] Products v3 (Automation) {Active}.json`, `[Kamul] [Integrations] Suppliers v3 (Automation) {Active}.json`, `[Kamul] [Integrations] Bill v3 (Automation) {Active}.json`, `[Kamul] [Integrations] Purchase Order v2 (Automation) {Active}.json`, `[Kamul] [Integrations] Update Pending Documents v1 (Automation) {Active}.json`, and the named queries above. `Kamul-Brands`, `Kamul-Clients`, `Kamul-Products` and `Kamul-Suppliers` are each exported with their own scheduler `isActive: false` — but `Kamul-Integration Schedule`'s scheduler **is** active, runs daily, and enqueues all four directly by automation id with `since: yesterday`. So the daily master-data sync is live; only each automation's own (now-redundant) standalone schedule is switched off, most likely because they were consolidated under the single orchestrator. #### How It Works 1. `Kamul-Integration Schedule` runs daily and enqueues `Kamul-Brands`, `Kamul-Clients`, `Kamul-Products`, `Kamul-Suppliers` as background work, each with `since: `. 2. Each pull calls a Kamul export endpoint (`GET {host}/api/exportdata/marcaget|entidadget|productoget?fecha=...`, entities filtered by `IDTipoEntidad=CLT` for clients / `PRV` for suppliers), resolves each record against Skills Workflow (`Kamul-GetBrand` / `Kamul-GetClient` / `Kamul-GetProduct` / `Kamul-GetSupplier`), and creates or updates it. New clients are also transitioned to the right stage via `Kamul-GetClientTransitionByName`. 3. `Kamul-Bill` and `Kamul-PurchaseOrder`, triggered on demand, build the outbound payload (`Kamul-BillById` / `Kamul-PurchaseOrderById`, plus an ISO currency-code lookup), send it to Kamul (`POST {host}/api/integraptos/factura` or `.../ordencompra`), and write the result back onto the document. 4. `Kamul-UpdatePendingDocuments`, triggered on demand, runs `Kamul-DocumentsPending` to find bills/purchase orders still waiting, re-queries Kamul for each by its external id (`GET .../integraptos/factura?PresupuestoID=...&OrigenDatos=Skills`, `.../ordencompra?OrdenCompraID=...`), and patches the document (`PATCH /api/bills/{id}`, `PATCH /api/purchase-orders/{id}`) once Kamul has an answer. #### External System Contact Points - Kamul API (`{host}` / `{hostUat}` from a `Config` configuration key — note `Kamul-PurchaseOrder` and `Kamul-UpdatePendingDocuments` use `hostUat`, suggesting purchase orders and status polling may run against a UAT/test Kamul environment rather than production; see Open Questions): `GET /api/exportdata/marcaget`, `.../entidadget`, `.../productoget`; `POST /api/integraptos/factura`, `.../ordencompra`; `GET /api/integraptos/factura`, `.../ordencompra` (status polling). - Skills Workflow's own API/analytics: the named queries above; `POST /api/v3/brands`, `POST /api/v3/commercial-clients`, `POST /api/v3/billing-clients`, `POST /api/v3/commercial-client-companies`, `POST /api/v3/commercial-products`, `POST /api/v3/billing-products`, `POST /api/v3/commercial-product-companies`, `POST /api/v3/suppliers`, `PATCH /api/bills/{id}`, `PATCH /api/purchase-orders/{id}`; `GET /api/v3/iso-codes/lookup`. #### Configuration - A `Config` configuration key — holds Kamul's `host`, `hostUat` and credentials. Values are not part of the export. #### Open Questions - `Kamul-PurchaseOrder` and `Kamul-UpdatePendingDocuments` call `Config.hostUat` while the master-data pulls and `Kamul-Bill` call `Config.host` — whether this is intentional (a genuinely separate UAT integration for those flows) or a leftover from testing is not determinable from the export. - `Kamul-GetStageByName` isn't called by any exported automation. --- ## Media360 URL: https://documentation.skillsworkflow.com/docs/integrations/media360 Summary: Media360 is the agency's media and financial back office. ### Description This article describes the integration between **Media360** and `Skills Workflow`. Media360 is the agency's media and financial back office. This integration is the widest of the financial integrations: it keeps the client and supplier base aligned in both systems, and it pushes the whole commercial and billing cycle produced in Skills Workflow — projects, contracts, bills, credit notes, supplier invoices and supplier notes — into Media360, so that finance never has to re-enter a document that was already approved by the operational teams. --- ### Data Exchange Technology The integration connects directly to the Media360 database. There is no file exchange and no additional application to install on the agency side; the connection is configured once, at deployment, by Skills Workflow. The integration runs on a schedule, company by company. Each company configured on the tenant has its own Media360 identification and its own document type mapping. Every document exported keeps its Media360 identifier in Skills Workflow. That identifier is what allows the integration to tell an already-exported document from a new one, and to send updates for documents that changed after they were first exported. --- ### Data Exchange (To Skills Workflow) The following master data is received from Media360: **Clients** — created and updated in Skills Workflow as Billing Clients and Commercial Clients, with the company links, identification, address, city and country details held in Media360. Clients that Media360 deactivates are moved to the stage configured in **Commercial Client Cancel Stage**. **Suppliers** — created and updated in Skills Workflow as Suppliers. --- ### Data Exchange (From Skills Workflow) The following are sent to Media360: | Document | What is sent | | --- | --- | | Services | The service catalogue maintained in Skills Workflow | | Projects | Projects opened in Skills Workflow, with the code built from the company **Code** and **Code Letter** | | Contracts | Contracts associated with those projects | | Bills | Bills of the type configured in **Bill Document Type**, with their items | | Client Credit Notes | Credit notes of the type configured in **Client Credit Note Document Type**, with their items | | Supplier Invoices | Supplier invoices of the type configured in **Supplier Invoice Document Type**, with their items | | Supplier Notes | Supplier notes of the type configured in **Supplier Note Document Type**, with their items | After the first export pass, the integration runs a second pass over bills, client credit notes, supplier invoices and supplier notes to send **changes** made to documents that had already been exported. This means a document corrected in Skills Workflow after it was sent does not have to be corrected manually in Media360 as well. The workflow state of exported documents is also kept aligned, so the financial status visible in Skills Workflow reflects what happened to the document downstream. --- ### Settings the Agency Controls The integration is configured per company, from the integration settings area in Skills Workflow: | Setting | What it does | | --- | --- | | Id | Identifier of this company in Media360 | | Code | Company code used when building document codes | | Code Letter | Letter used together with the code | | Commercial Client Cancel Stage | Stage applied to commercial clients that Media360 deactivates | | Bill Document Type | Which Skills Workflow document type is exported as a bill | | Client Credit Note Document Type | Which document type is exported as a client credit note | | Supplier Invoice Document Type | Which document type is exported as a supplier invoice | | Supplier Note Document Type | Which document type is exported as a supplier note | | Administrator Mail | Address that receives the error notifications for this company | | Log Level Type | How much detail is written to the integration log | --- ### What the Agency Needs to Provide - Access to the Media360 database, with a dedicated user for Skills Workflow. - The Media360 identifier, code and code letter for each company. - Confirmation of which Skills Workflow document types map to bills, client credit notes, supplier invoices and supplier notes. - An administrator e-mail address to receive integration notifications. --- ### Monitoring and Error Handling Every run writes to the integration log inside Skills Workflow, at the level of detail chosen in **Log Level Type**. The log is cleared at the start of each run, and records both the documents processed and the ones that failed. A summary e-mail is sent to the address configured in **Administrator Mail**. A document that fails does not stop the run; the integration continues with the remaining documents and reports everything at the end. --- ### Good to Know - Documents are matched by their Media360 identifier. It is stored on the Skills Workflow document and should not be edited manually. - Only documents of the configured types are exported. If a new document type is introduced, the mapping has to be updated for it to be picked up. - Master data flows only from Media360 into Skills Workflow; documents flow only from Skills Workflow into Media360. --- ## Microsoft Entra URL: https://documentation.skillsworkflow.com/docs/integrations/single-sign-on-sso/microsoft-entra Summary: In this article, you'll learn how to integrate with Microsoft Entra. In this article, you'll learn how to integrate with Microsoft Entra. When you integrate Skills Workflow with Microsoft Entra, you can: * Control in Microsoft Entra who has access to Skills Workflow. * Enable your users to be automatically signed-in to Skills Workflow with their Microsoft Entra accounts. --- ### Prerequisites To get started, you need the following items: * An Microsoft Entra subscription. * Skills Workflow single sign-on (SSO) enabled subscription. ### Installation via Gallery Please follow the instructions from Microsoft website [Tutorial: Microsoft Entra SSO integration with Skills Workflow](https://learn.microsoft.com/en-us/entra/identity/saas-apps/skills-workflow-tutorial) --- ## Microsoft Sharepoint URL: https://documentation.skillsworkflow.com/docs/integrations/cloud-storage/microsoft-sharepoint Summary: Skills Workflow integrates with Sharepoint. Skills Workflow integrates with Sharepoint. The integration allows you to: - Create automatically and organize a file structure in SharePoint - Access to the folders and files available in SharePoint - Have your team get quick and easy access to the files in Sharepoint - Share the direct link to the files in Sharepoint in comments Files When a file is uploaded into SharePoint, it is automatically available in Skills Workflow. - You can share your file by going into your document and easily select the file - It will be available to add it into the document's description - Or to post it on the document's feed When a file is uploaded in a comment from the Hard Drive: - The file is uploaded to SharePoint - A link is created and posted in the comment - A thumbnail will be also available in the comment --- Mappings Sharepoint integration requires mappings between: - Client and Sharepoint Site - Project and Sharepoint Sub-Site - File's Tag and Category --- Files When a file is uploaded in Skills Workflow, it will be available on the corresponding Sharepoint Sub-Site. Whenever a document is created in Skills Workflow, a folder is created under its parent document folder. The structure of the folders in Skills Workflow is: - Root - Client (Sharepoint Site) - Project (Sharepoint Sub-Site) --- Synching The synching is performed by a background process. Whenever a document is created or his folder name is changed in Skills Workflow, the process will replicate it in Sharepoint. - The synching process is from Skills Workflow to Sharepoint - Skills Workflow has a reference of the ID of the files and folders in SharePoint - The users will see the same file structure (starting on the root) in both systems Auth The integration with SharePoint requires: - An application registration in the Azure Active Directory - Application (client) ID - Directory (tenant) ID - Client secret - API permission to the Sharepoint Please check below step by step how to configure an App: 1. Access into the Azure AD and create a new App with the following details 2. Create client secret 3. Add to the App the API permission to your manage your SharePoint --- ## Microsoft Teams URL: https://documentation.skillsworkflow.com/docs/integrations/microsoft-teams Summary: Post a card to a Microsoft Teams channel whenever a chosen event happens in Skills Workflow. ## 1. Overview Post a card to a Microsoft Teams channel whenever a chosen event happens in Skills Workflow. The integration is built from five pieces: - **Webhook** — triggers the automation on the event you configure. - **System Parameters** — store the Teams channel webhook URL(s) to post to. - **Template** — the Adaptive Card JSON, filled in with the query's data. - **Named Query** — retrieves the data that fills in the Template. - **Automation Workflow** — ties everything together. Flow: 1. The **Webhook** fires on the configured event and triggers the **Automation Workflow**. 2. The automation runs the **Named Query**. 3. The automation fills in the **Template** with the query results. 4. The automation posts the card to the URL(s) stored in **System Parameters**. None of this is tied to one scenario: - The webhook's event can be any [Skills Workflow webhook event](../build-and-extend/api/webhooks#event) — `StageUpdated` on `Deliverable` (posting whenever a job changes stage) is just one example. - The Named Query and Template can be swapped or edited to show different data, independently of the webhook. - System Parameters can hold more than one destination URL, so the same automation can post to several Teams channels — one per project or client, for instance. --- ## 2. Package Contents To enable this integration, import all five items: | Item (Marketplace name) | Description | |---|---| | Webhook | Triggers the automation on the event you configure — see [Webhooks](../build-and-extend/api/webhooks) | | System Parameters | Stores the Teams channel webhook URL(s) — one per channel if you need to post to more than one | | Template | The Adaptive Card JSON posted to Teams | | Named Query | Retrieves the data that fills in the Template's JSON | | Automation Workflow | Runs the query, fills in the Template, and posts the result to Teams | The **Item** column lists each component's exact Marketplace name — the same in every tenant, so it works for searching your own tenant or a client's. Templates and Named Queries are general Skills Workflow objects, not exclusive to this integration — reuse an existing one or build a new one as needed. --- ## 3. The Card Template The **Template** is the Adaptive Card JSON posted to Teams. A basic one needs this envelope: ```json { "type": "message", "attachments": [ { "contentType": "application/vnd.microsoft.card.adaptive", "content": { "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.5", "body": [ { "type": "TextBlock", "text": "{{['NamedQuery'].data[0].Title}}", "weight": "Bolder", "size": "Medium", "wrap": true }, { "type": "FactSet", "facts": [ { "title": "Number", "value": "{{['NamedQuery'].data[0].Number}}" }, { "title": "Status", "value": "{{['NamedQuery'].data[0].Status}}" }, { "title": "Updated by", "value": "{{['NamedQuery'].data[0].UpdatedBy}}" }, { "title": "Updated on", "value": "{{['NamedQuery'].data[0].UpdatedOn}}" } ] }, { "type": "TextBlock", "text": "{{['NamedQuery'].data[0].Description}}", "wrap": true } ], "actions": [ { "type": "Action.OpenUrl", "title": "Open in Skills Workflow", "url": "{{['NamedQuery'].data[0].Link}}" } ] } } ] } ``` Replace `NamedQuery` with the alias given to the Named Query step in the Automation Workflow, and the field names with whatever the query actually returns. Two kinds of placeholder are used: | Data type | How to insert it | |---|---| | Plain text or number | Inside quotes: `"{{['NamedQuery'].data[0].Field}}"` | | JSON array (e.g. chart data) | No quotes: `"data": {{['NamedQuery'].data[0].ArrayField}}` | The card is posted as an **Adaptive Card**, through the incoming webhook created via the Workflows app (see [Section 8](#8-configuring-the-incoming-webhook-in-microsoft-teams)). --- ## 4. Example: Deliverable Stage Change A common request: post to Teams whenever a Deliverable moves to a specific workflow stage. Using the five pieces from [Section 2](#2-package-contents): - **Webhook** — Event `StageUpdated`, Document `Deliverable`, filtered on `ToWorkflowStageName` for the stage that should trigger it. - **Template** — the default card from [Section 3](#3-the-card-template) already fits: title, number, status, who triggered it, when, a description, and a link back to the Deliverable. - **Named Query** — returns one row with the Deliverable's number, title, stage, the user who triggered the event, the event timestamp, its latest brief or description, and a link to it in Skills Workflow. - **Automation Workflow** — receives the webhook payload, runs the query, fills in the Template, and posts the result to the Teams URL stored in [System Parameters](#6-configuration). If a ready-made Marketplace package matches this scenario, import it (see [Section 5](#5-installation)) instead of building each piece by hand. One deployed Named Query for this pattern, `GetDeliverableById` (v1, Active — `[Microsoft Teams] [Integrations] GetDeliverableById v1 (Query) {Active}.json`), looks up a job by id: ```sql with brief as ( select top 1 db.Text from DocumentBrief db where db.DocumentOid = @Oid order by db.CreatedOn desc ) select d.Number, d.Project, d.Name as Title, d.CreatedOnUtc as CreatedOn, b.Text as Description from JobLookup d, brief b where d.Id = @Oid ``` It returns `Number`, `Project`, `Title`, `CreatedOn` and `Description` — narrower than the Status/UpdatedBy/UpdatedOn/Link fields shown in the sample card above, so the Template and card layout paired with this particular query would only be able to show these five fields. The Automation Workflow, Webhook, Template and System Parameters that use this query were not included in the export, so the rest of this instance's wiring is not determinable. --- ## 5. Installation Search the Marketplace for a package matching your scenario and import it — e.g. **Microsoft Teams Deliverable Notifications** for the stage-change example in [Section 4](#4-example-deliverable-stage-change). No match? Build the five items yourself (see [Section 2](#2-package-contents)). Items to import: 1. Configuration Keys or System Parameters 2. Named Query 3. Template 4. Automation Workflow 5. Webhook --- ## 6. Configuration Configure the **System Parameters** the automation reads at runtime: - Teams channel webhook URL(s) — one per channel if posting to more than one - Skills Workflow base URL used in the card link - Any filter values the webhook needs (e.g. workflow stage name, project ID) This still requires importing the query, template, automation, and webhook — Configuration Keys only supply values to those items, they don't replace them. --- ## 7. Prerequisites Before setting up the integration, make sure you have: - Access to the **Marketplace** - A Microsoft Teams channel that should receive the card - A valid Microsoft Teams incoming webhook URL for that channel (see [Section 8](#8-configuring-the-incoming-webhook-in-microsoft-teams) to create one) - A Skills Workflow **Webhook** configured for the event that should trigger the automation (see the [Webhooks reference](../build-and-extend/api/webhooks)) - A **Template** with the Adaptive Card definition - The values required by the **Configuration Keys** or **System Parameters** --- ## 8. Configuring the Incoming Webhook in Microsoft Teams Classic Office 365 Connectors (the original "Incoming Webhook" connector type) are being retired by Microsoft. Teams now generates webhook URLs through the **Workflows** app, which is powered by Power Automate. The steps below reflect this current approach. See [Microsoft's official documentation](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook) for the most up-to-date instructions. 1. In **Microsoft Teams**, go to the team and channel that should receive the cards. 2. Select **More options (...)** next to the channel name. 3. Select **Workflows**. 4. In the search box, type `Send webhook alerts to a channel` and select it from the **Templates** list. 5. Under **Parameters**, confirm the **Team the channel is in** and the **Channel**, then select **Save**. The workflow is named automatically, for example `Send webhook alerts to Announcements` based on the channel. You can rename it later using the pencil icon next to the title. 6. The workflow opens showing it as **Active**. Select **Copy webhook link** to copy the generated webhook URL. 7. Paste this URL into the Skills Workflow **Configuration Keys** or **System Parameters** value for the Microsoft Teams incoming webhook. ### Permissions - Creating a workflow requires access to the **Workflows** app in Teams and, depending on tenant Power Automate licensing and policies, may require admin approval. - Team owners can control who is allowed to create, update, or remove connectors and workflows for a channel under **Team settings > Member permissions > Allow members to create, update, and remove connectors**. ### Managing the webhook later To disable or remove the integration on the Teams side, open the workflow itself (as shown in the screenshot above) and select **Turn off** to pause it or **Delete** to remove it permanently. You can also reach the same workflow from the **Workflows** app, under **Your workflows**, by selecting **More actions (...)** next to it. Turning off or deleting the workflow stops new cards from being posted to Teams but does not change the Skills Workflow configuration. If you create a replacement workflow, update the stored webhook URL in the Configuration Keys or System Parameters accordingly. --- ## 9. Summary - Import or build the five items: Webhook, System Parameters, Template, Named Query, Automation Workflow - Configure the required Configuration Keys or System Parameters - Test the trigger event - Confirm the card arrives in Microsoft Teams There is no need to create the query, template, automation workflow, webhook, or configuration entries manually if you're importing an existing package. --- ## MMS URL: https://documentation.skillsworkflow.com/docs/integrations/mms Summary: MMS holds the agency's master data — the official list of clients, products, suppliers, services and people. ### Description This article describes the integration between **MMS** and `Skills Workflow`. MMS holds the agency's master data — the official list of clients, products, suppliers, services and people. This integration takes care of loading that master data into Skills Workflow and keeping it aligned, so that teams always plan and book work against the same client, product and service catalogue that the rest of the group uses. It is a one-way integration: MMS is the source of truth, and Skills Workflow follows it. --- ### Data Exchange Technology MMS publishes a master-data file on an FTP server. Skills Workflow connects to that server on a schedule and looks for files whose name contains `_SKILLS`, in JSON format. Files are processed in order, oldest first. Every file that has already been imported is recorded, so a file is never processed twice — even if it is still sitting on the server. Once a file has been handled it is moved out of the working folder. The FTP connection details are taken from the default company configured for the integration; the contents of the file are then distributed across all the companies on the tenant. --- ### Data Exchange (To Skills Workflow) A master-data file can carry the following blocks: | Block | What it contains | | --- | --- | | Companies | The list of companies referenced by the rest of the file | | Clients | The client catalogue | | Client Companies | Which clients belong to which company | | Products | The product catalogue, with the client each product belongs to | | Suppliers | The supplier catalogue | | Supplier Companies | Which suppliers are available to which company | | Services | The service catalogue | | Supplier Services | Which services each supplier provides | | Users | The people catalogue | | User Client Companies | Which users are assigned to which client | From these blocks, Skills Workflow creates and maintains: - **Billing Clients** and **Commercial Clients**, together with the companies they are linked to - **Billing Products** and **Commercial Products**, together with the companies they are linked to - **Suppliers** - **Services**, and the suppliers that provide them - **Employees and Users**, with their profiles - **Commercial Client Users** — the assignment of people to clients Records carry an inactivation date in the file. When that date is filled in, the corresponding record is deactivated in Skills Workflow rather than deleted, so history and reporting are preserved. Commercial clients that are deactivated are moved to the stage configured in **Commercial Client Cancel Stage**. New users are created with the department, typology and profile configured as defaults for the company, and with an SSO user name built using the suffix configured in **SsoUserName Ends With**. --- ### Settings the Agency Controls The integration is configured per company, from the integration settings area in Skills Workflow: | Setting | What it does | | --- | --- | | Ftp Host Ip / Ftp Host Port | Address of the FTP server | | Ftp Username / Ftp Password | Credentials the integration connects with | | Ftp Directory | Folder that is watched for new files | | Commercial Client Cancel Stage | Stage applied to commercial clients that MMS deactivates | | Default User Department | Department given to users created by the integration | | Default User Typology | Typology given to users created by the integration | | Default User Profile | Roles given to users created by the integration | | SsoUserName Ends With | Domain suffix used to build the SSO user name | | Administrator Mail | Address that receives the error notifications for this company | | Log Level Type | How much detail is written to the integration log | --- ### What the Agency Needs to Provide - An FTP server, the folder to watch, and the credentials for it. - The MMS master-data exports delivered into that folder, with `_SKILLS` in the file name and in JSON format. - The default department, typology and profile to apply to imported users, and the SSO domain suffix. - An administrator e-mail address to receive integration notifications. --- ### Monitoring and Error Handling Every run writes to the integration log inside Skills Workflow, at the level of detail chosen in **Log Level Type**. The log is cleared at the start of each run. Failures are reported both at file level and at record level, and a summary e-mail is sent to the address configured in **Administrator Mail**. A record that fails does not stop the file: the remaining records are still processed and everything that failed is reported at the end. --- ### Good to Know - MMS is the source of truth for the catalogues it covers. Changes made manually in Skills Workflow to clients, products, suppliers or services will be overwritten by the next file. - Files are imported once and only once. To reload a file, it has to be delivered under a new name. - Nothing is deleted. Records removed from MMS are deactivated in Skills Workflow. --- ## Okta URL: https://documentation.skillsworkflow.com/docs/integrations/single-sign-on-sso/okta Summary: In this article, you'll learn how to integrate with Okta SSO. In this article, you'll learn how to integrate with Okta SSO. When you integrate Skills Workflow with Okta, you can: * Control in Okta who has access to Skills Workflow. * Enable your users to be automatically signed-in to Skills Workflow with their Okta accounts. --- ### Prerequisites To get started, you need the following items: * An Okta subscription. * Skills Workflow single sign-on (SSO) enabled subscription. --- ### Installation Follow these steps to enable Okta SSO in the Admin center. 1. In the **Admin center**, on the left pane navigate to **Applications** and click on **Create New App**. 2. For Sign-in method, select **SAML 2.0**, and click **Next**. 3. On the **General Settings**, configure the **App Name** and **App Logo**. 4. On the **SAML Settings** section, perform the following steps: - In the **Single Sign-on URL** text box, type the URL: `https://auth.skillsworkflow.com/saml2/acs` - In the **Audiance URI (SP Entity ID)** text box, type the URL: `https://auth.skillsworkflow.com/saml2` - Leave the other settings with the default values 5. On the **Are you a Customer or partner** section, select the **I'm an Okta customer adding an internal app**, and then click on **Finish**. 6. Once the app is created, go to the **Assignments** tab, assign the people or groups that will have access to use the SSO App. 7. On the **Sign On** tab, click on the **View SAML setup instructions**. 8. Copy the configurations to the system SSO configuration, by accessing the **Maintenance** and navigating to **SSO page**. - Okta **Identity Provider Single Sign-On URL** to the system `SSO Service Url` - Okta **Identity Provider Issuer** to the system `Entity ID` - Okta **X.509 Certificate** to the system `Certificate` --- ### Improving user experience To provide a better user experience while using OKTA and Skills Workflow integration, it is recommended to: - Not displaying the SSO app to the users - But create a Bookmark App within OKTA that will provide the full SSO user experience Please proceed with the following steps: 1. On the **General tab**, set the **application visibility** as **not visible** to the users 3. Go to **Applications**, and create a **Bookmark App**. - Set the **Application Name** as Skills Workflow - Set the **URL** with the Tenant URL followed by /SSOLogin - And assign the users to this new **Bookmark App** - Once it is created, go back to Bookmark App settings and under **General** tab, add a **Logo** to the Bookmark App --- ## Omie URL: https://documentation.skillsworkflow.com/docs/integrations/Omie Summary: Omie is the Brazilian cloud ERP many agencies use for accounting and tax compliance — including issuing the NFS-e, the electronic service invoice that is a… ### Description This article describes the integration between **Omie** and `Skills Workflow`. Omie is the Brazilian cloud ERP many agencies use for accounting and tax compliance — including issuing the *NFS-e*, the electronic service invoice that is a legal requirement for billing services in Brazil. Skills Workflow is where the work being billed is run. This integration closes the billing loop end to end, and its distinguishing feature is that it goes **both ways on the same document**: - **Clients are pushed out to Omie** every day, so accounting is registering invoices against the same client records the agency works with. - **A bill is sent to Omie** as a service order (*Ordem de Serviço*) when it is ready. - **The issued invoice comes back.** When Omie issues the NFS-e for that service order, the invoice reference is written onto the bill in Skills Workflow automatically. That last step is what makes it worth having. Without it, someone has to watch Omie for the invoice to be issued and then go back and record the number against the job — which is exactly the kind of manual reconciliation that goes stale. With it, the bill in Skills Workflow shows its own tax invoice number, so operations and finance are looking at the same fact. --- ### Data Exchange Technology The exchange runs over the Omie web API, using credentials configured by the agency. No files and no locally installed application are required. Three things happen on different rhythms: - **The client push runs daily**, sending clients registered or changed that day. - **Bills are sent as they become ready**, not on a schedule. - **The NFS-e comes back when Omie issues it** — Omie calls Skills Workflow, so the invoice number lands as soon as it exists rather than waiting for the next run. A bulk load is available for the initial population, and an on-demand client update for ad-hoc corrections. --- ### Data Exchange (From Skills Workflow) | Sent to Omie | As | | --- | --- | | **Clients** | Omie customers, with their billing details and country resolved against Omie's own country list | | **Bills** | Service orders (*Ordem de Serviço*), with their line items | --- ### Data Exchange (To Skills Workflow) | Received from Omie | Result | | --- | --- | | **NFS-e issued** for a service order | The electronic invoice reference is written onto the matching bill | --- ### What the Agency Needs to Provide - **An Omie account with API access**, plus the application key and secret for Skills Workflow. - **Omie configured to notify Skills Workflow** when an NFS-e is issued, so the reference can be returned automatically. - **Clients whose company and billing setup exist in Omie** — see *Good to Know*. --- ### Monitoring and Error Handling If a bill cannot be resolved to a valid company or client in Omie, the integration stops on that bill and reports it rather than sending an incomplete document to an accounting system. The remaining bills are unaffected. --- ### Good to Know - **The client has to reach Omie before its bills can.** The daily client push is what makes billing possible, so a brand-new client billed the same day may need the push to run first. - **Bills are matched to their Omie service order**, and the service order to its NFS-e, so the chain from job to tax invoice is traceable in both directions. - **The invoice number arrives when Omie issues it**, which may be some time after the bill is sent — a bill without a number yet has not necessarily failed. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Omie-Clients | Automation | 2 | Active | Daily: sends today's new/changed clients to Omie | | Omie-Clients-FirstLoad | Automation | 1 | Active | On-demand variant of the same client push, without the "today" date filter — for an initial bulk load | | Omie-BulkClientUpdate | Automation | 1 | Active | On-demand: pushes a client update to Omie and updates its billing e-mail | | Omie-Send Bills | Automation | 6 | Active | Sends a bill and its items to Omie as a service order | | Omie-Recieve_NFS-e | Automation | 2 | Active | Inbound: receives Omie's NFS-e notification and patches the matching bill | | Omie-GetClientTodayFormatted | Query | 1 | Active | Returns today's date, used to filter which clients to send | | Omie-GetBillingClient | Query | 1 | Active | Resolves the billing client/company data for a client push | | Omie-GetBillById | Query | 4 | Active | Resolves a bill's data for sending, or a `company`/`client` error status if not resolvable | | Omie-getBillItemsById | Query | 2 | Active | Resolves a bill's line items for sending | | Omie-GetBillByOrdemServico | Query | 1 | Active | Looks up the Skills Workflow bill matching an Omie service-order id | | Omie-UpdateEmailFactura | Query | 1 | Active | Used by the bulk client update to refresh a client's billing e-mail | Source: `[Omie] [Integrations] Clients v2 (Automation) {Active}.json`, `[Omie] [Integrations] Omie-Clients-FirstLoad v1 (Automation) {Active}.json`, `[Omie] [Integrations] Omie-BulkClientUpdate v1 (Automation) {Active}.json`, `[Omie] [Integrations] Send Bills v6 (Automation) {Active}.json`, `[Omie] [Integrations] Recieve NFS-e v2 (Automation) {Active}.json`, and the six named queries above. #### How It Works 1. **Clients** — daily, `Omie-Clients` runs `Omie-GetClientTodayFormatted` to get today's date, then for each client changed/created today: `POST https://app.omie.com.br/api/v1/geral/clientes/` to upsert the client in Omie, `Omie-GetBillingClient` to resolve the matching billing client, `POST /api/v3/billing-clients`, and a country lookup (`.../geral/paises/` in Omie, matched to a Skills Workflow country by ISO code) before writing the result back via `PUT /api/v3/documentUserFieldValues`. `Omie-Clients-FirstLoad` and `Omie-BulkClientUpdate` reuse the same Omie client endpoint for an initial load / ad-hoc update outside the daily run. 2. **Sending a bill** — `Omie-Send Bills`, triggered on demand for a specific bill, runs `Omie-GetBillById`; a `company`/`client` status halts with an internal notification instead of sending. Otherwise it fetches the bill's items (`Omie-getBillItemsById`), ensures the client exists in Omie (`.../geral/clientes/`), and creates the service order (`POST .../servicos/os/`), writing the result back via `PUT /api/v3/documentUserFieldValues`. 3. **Receiving the invoice** — `Omie-Recieve_NFS-e` is called directly by Omie (its payload uses Omie's own field name `event.id_os`, not a Skills Workflow event shape) when an NFS-e is issued for a service order. It looks up the matching bill via `Omie-GetBillByOrdemServico` and patches it (`PATCH /api/bills/{id}`) with the invoice reference. #### External System Contact Points - Omie API (`app.omie.com.br/api/v1/`): `POST /geral/clientes/` (create/update client), `POST /geral/paises/` (country lookup), `POST /servicos/os/` (create service order). - Inbound: Omie calls this tenant's `Omie-Recieve_NFS-e` endpoint directly when an NFS-e is issued. - Skills Workflow's own API/analytics: the named queries above; `POST /api/v3/billing-clients`, `PUT /api/v3/documentUserFieldValues`, `PATCH /api/bills/{id}`. #### Configuration - Configuration key **`Omie`** — holds the Omie API credentials used by `Omie-Send Bills` (and presumably the other Omie-calling automations, though only this one's `ConfigurationKeys` action was inspected in depth). Values are not part of the export. #### Open Questions - What triggers `Omie-Send Bills` (a webhook, a manual action, another automation) is not part of this export — only that it expects a bill id in an HTTP request body shaped like a Skills Workflow event. - The exact authentication Omie uses to call `Omie-Recieve_NFS-e` back is not shown in this automation. --- ## PowerBI Integration With Csv Files URL: https://documentation.skillsworkflow.com/docs/integrations/powerbi Summary: Produces a Power BI Workspace using data aquired from SkillsWorkflow. ### Description Produces a Power BI Workspace using data aquired from SkillsWorkflow. Data is extracted from a Query installed in the Tenant. The Analytics service runs de Query and sends it to a CSV file. The CSV File is then added as a Data Source in the Power BI Workspace. --- ### Configuration #### Skills Workflow - Go into the tenant in Maintenance and create Query. - Name the Query with the prefix "Power BI - " (e.g., Power BI - Active Jobs) - Set the Categoty to "Power BI" - Create a new Schedule to run the Query using the Configuration. - Set the running times of the File generation based on the Query that is run - Set the name of the File to generate. No spaces are allowed (e.g., PowerBI-ActiveJobs) - The Schedule will generate an URL for the File that is generated. - Running - The Query can be forced to be run manually. - Go into the Configuration and run the specified Schedule. - This will execute the Query and generate the File. #### Workspaces The Workspaces in Power BI will have Data Sources pointing to the URL of the Files. The URL of the Files is shown in the Schedules that are created in Configuration.The data refresh (i.e., when Power BI reads the data from the Files) can be set to a minimum of every 30 minutes. ##### Setup - In Power BI, create a Workspace. - Go into the Data Source section and add a new Web data source. - Get the URL for the generated file from the Schedule generation and paste it here. - The data will be available in the Report pages for use. #### Schedule updates on Power BI After publishing your Power BI dashboard you need to schedule the updates in the Office365 environment. You have to ask Skills Workflow team to send the credentials for each datasource. Once you get it, in the Power BI portal go to desired Dataset and click on dataset credentials. After changing all datasets setup, go to Scheduled Update: - Choose Activate and set the time that you want to run the update - Click Apply --- ### Power Bi Integration with API #### Overview There was a need to export job data from the system to Power Bi #### Data Exchange The scope of this article includes an explanation of how to get data from the system. Skills Workflow has available specific APIs to extract information prepared to be used in Power BI dashboards, so you can use it to get the data out from the system. You can get the data using REST calls. Regarding Power BI, you should request to the team the corresponding URL to export data, ie: - [https://apiv2-demo.skillsworkflow.com/api/integration-workflows/0bdc05b7-3b3d-41f3-9e84-b6f75d3a6307/execute](https://apiv2-demo.skillsworkflow.com/api/integration-workflows/0bdc05b7-3b3d-41f3-9e84-b6f75d3a6307/execute) #### Configuration There are 2 ways to use Skills APIs in PowerBI, both you need to ask Skills’ team the credentials to access the data. Skills Team will send you the information bellow: - URL parts - HTTP request headers parameters - X-AppTenant - X-AppId - X-AppSecret If you’re using REST API Endpoint (GET): The APIv2 Apis are normally created with a POST. In this scenario open a blank query and add the commands bellow to get the data: ``` javascript let body = "{}", Data= Web.Contents("URL Provided", [Content=Text.ToBinary(body) in #"Data" ``` Once you have the data extracted you have to transform it to create your dashboard. #### Transform Your Data To be able to manage your data in Power Bi, you will need to follow some steps: - Transform column into json: - Transform list into json - Convert data into table - Set configuration to open as Json - Split data into columns - The data will be in columns --- ## Primavera URL: https://documentation.skillsworkflow.com/docs/integrations/primavera Summary: Primavera is where the agency's finance team works. ### Description This article describes the integration between the **Primavera** ERP and `Skills Workflow`. Primavera is where the agency's finance team works. This integration removes the double entry between the two systems: the master data finance already maintains in Primavera — clients, suppliers, VAT, currencies, payment conditions — flows into Skills Workflow so the operational teams book work against the correct records, and the financial documents produced by those teams flow back into Primavera for invoicing and payment. --- ### Data Exchange Technology The exchange is based on **views**. The ERP is installed locally on the agency's server, and the integration reads and writes through views made available in the system. --- ### What Comes Into Skills Workflow Primavera is the source of truth for the financial master data: | Received from Primavera | Why it matters | | --- | --- | | Clients | Teams book work against the same client records finance invoices | | Suppliers | Purchase orders and supplier invoices reference real, approved suppliers | | Articles | The billable item catalogue | | VAT | Correct tax rates on every document | | Currency | Multi-currency work is valued consistently in both systems | | Payment Conditions | Payment terms travel with the client | | Expense Item Types | Expenses are classified the way finance expects | | Reversal Reasons | Credit notes carry a reason finance recognises | | Employees | People records stay aligned | New records created in Primavera are created automatically in Skills Workflow, and later changes are synchronised. --- ### What Goes Out To Primavera The financial documents produced in Skills Workflow are sent to Primavera: - Bills - Client Credit Notes - Expenses - Purchase Orders - Supplier Invoices - Supplier Notes Documents are exported at item level, so Primavera receives the detail behind each total rather than a single lump sum. --- ### What the Agency Needs to Provide - A Primavera installation reachable by the integration, with the required views available. - Confirmation of which companies are in scope. - Agreement on how master data records are identified on both sides, so records match rather than duplicate. --- ### Good to Know - Primavera is the source of truth for master data. Changes made manually in Skills Workflow to clients, suppliers, VAT or currencies will be overwritten. - Skills Workflow is the source of truth for the documents it produces. - Records are matched by their external identifier. Changing it manually on either side will cause duplicates. --- For the field-by-field mappings, see the **[Technical Reference](./reference)**. --- ## Primavera — Technical Reference URL: https://documentation.skillsworkflow.com/docs/integrations/primavera/reference Summary: This is the Documentation of how the Integration between the ERP Primavera and Skills Workflow work. This page is the interface specification for the Primavera integration — file formats, naming conventions and field-by-field mappings. It is written for the team implementing the exchange. For what this integration does and how it is configured, see **[Primavera](./)**. ### Description This is the Documentation of how the Integration between the ERP Primavera and Skills Workflow work. This documentation is for Skills Workflow located in the Cloud. --- ### Data Exchange Technology Based on Views. The ERP will be installed locally on a server. The scope of data exchanged on this integration includes: --- ### From Primavera to Skills Workflow Master data - Clients - Suppliers - VAT - Currency - Payment Conditions - Articles - Reversal Reasons --- ### From Skills Workflow to Primavera Financial Documents - Expenses - Invoices/Bills - Purchase Orders --- ### Data Exchange (To Skills Workflow) This section describes the Data exchanged between systems. Please see the data exchanged. The data is exchanged with Views available in the system. Financial Documents - Expenses - Invoices/Bills - Purchase Orders --- ### Data Exchange (inbound) This section describes the Data exchanged between systems. Please see the data exchanged. The data is exchanged with Views available in the system. #### Articles are received by Skills Workflow. - New Articles created in Primavera are automatically created in Skills Workflow. - Any change in the Articles data is also synched with Skills Workflow. Articles Data Exchanged #### Fields that are populated in Skills Workflow are: - Id - Name - VatDeductiblePercentage - Action - Mappings #### Client Clients are received by Skills Workflow. - New Clients created in Primavera are automatically created in Skills Workflow. - Any change in the Clients data is also synched with Skills Workflow. #### Clients Data Exchanged Fields that are populated in Skills Workflow: - Id - Name - Street - Street2 - City - ZipPostal - StateProvince - TaxPayerNumber - PaymentCondition - Currency - Country - OtherDebtor - Action #### Currency Currencies are received by Skills Workflow. - New Currencies created in Primavera are automatically created in Skills Workflow. - Any change in the Currencies data is also synched with Skills Workflow. #### Currencies Data Exchanged Fields that are populated into Skills: - Id - Name - Buy - Sell - ValueRound - VatRound - PriceRound - Action #### Employee Employees are received by Skills Workflow. - New Employees created in Primavera are automatically created in Skills Workflow. - Any change in the Employees data is also synched with Skills Workflow. #### Employees Data Exchanged The fields that are populated into Skills Workflow: - Id - Name - Action #### Expense Item Type Expense are received by Skills Workflow. - New Expense Items created in Primavera are automatically created in Skills Workflow. - Any change in the Expense Items data is also synched with Skills Workflow. #### Expense Items Data Exchanged The fields that will be populated into CETA: - Id - Company - Name - Value - Vat - VatDeductiblePercentage - Action #### Expense Item Type Expense are received by Skills Workflow. - New Expense Items created in Primavera are automatically created in Skills Workflow. - Any change in the Expense Items data is also synched with Skills Workflow. #### Expense Items Data Exchanged The fields that will be populated into CETA: - Id - Company - Name - Value - Vat - VatDeductiblePercentage - Action #### Reversal Reason Reversal Reasons are received by Skills Workflow. - New Reversal Reasons are created in Primavera are automatically created in Skills Workflow. - Any change in the Reversal Reasons data is also synched with Skills Workflow. #### Reversal Reasons Data Exchanged The fields that will be populated into Skills Workflow: - Id - Company - Name - Action #### Supplier Suppliers are received by Skills Workflow. - New Suppliers' created in Primavera are automatically created in Skills Workflow. - Any change in the Suppliers' data is also synched with Skills Workflow. #### Suppliers' Data Exchanged The fields that will be populated into Skills Workflow: - Id - Name - Company - Street - Street 2 - City - ZipPostal - StateProvince - TaxpayerNumber - Payment Condition - Currency - OtherCreditor - Action #### Vat Vat values are received by Skills Workflow. - New Vat values created in Primavera are automatically created in Skills Workflow. - Any change in the Vat data is also synched with Skills Workflow. #### Vat Data Exchanged The fields that will be populated into Skills Workflow: - Id - Company - Name - Percentage - Action --- ### Data Exchange (To Skills Workflow) This section describes the Data exchanged between systems. Please see the data exchanged. The data is exchanged with Views available in the system. #### Bill Item Bill Items are sent by Skills Workflow. - New Bills Items' created in Skills Workflow are automatically created in Primavera. - Any change in the Bills data is also synched with Primavera. #### Bill Item Data Exchanged Fields that are populated in Primavera: - Oid - Name - CompanyId - EstimateId - EstimateHasProjectId - EstimateAccountCode - EstimateAccountName - EstimateAccountBeginDate - EstimateAccountEndDate - EstimateAccountBillingClient - BillId - BillingClient - OtherDebtor - Currency - Exchange - TotalValue - PaymentCondition - YourReference - Date - Due - CommercialClientName - ProjectNumber - ProjectName - ProjectSequence - ProjectYear - Project - ContractNumber - ContractName - ContractSequence - ContractYear - BillItemId - Article - Description - Vat - VatPercentage - UnitPrice - Discount - Quantity - ValueWithoutVat - VatValue - ValueWithVat - ExternalId - External - ExternalItemId - LineNumber - Remarks - AttentionLine - EstimateNumber - PrimaveraDocumentType - CostCenter - BillItemOrder - WorkflowStateId - PreviousWorkflowStateId - KeepOnError #### Client Credit Note Item Credit Client Notes are sent by Skills Workflow. - New Credit Client Notes created in Skills Workflow are automatically created in Primavera. - Any change in the Credit Client Notes data is also synched with Primavera. #### Credit Client Notes Data Exchanged Fields that are populated in Primavera: - Oid - Name - CompanyId - EstimateId - EstimateHasProjectId - EstimateAccountCode - EstimateAccountName - EstimateAccountBeginDate - EstimateAccountEndDate - EstimateAccountBillingClient - ClientCreditNoteId - BillingClient - OtherDebtor - Currency - Exchange - TotalValue - PaymentCondition - YourReference - Date - CommercialClientName - ProjectNumber - ProjectName - ProjectSequence - ProjectYear - Project - ContractNumber - ContractName - ContractSequence - ContractYear - ClientCreditNoteItemId - Article - Description - Vat - VatPercentage - UnitPrice - Discount - Quantity - ValueWithoutVat - VatValue - ValueWithVat - Chargeback - ReversalReason - BillItem - BillName - ExternalId - External - ExternalItemId - LineNumber - EstimateNumber - CostCenter - ClientCreditNoteItemOrder - WorkflowStateId - PreviousWorkflowStateId - BillNames - KeepOnError #### Expense Item Expense Items are sent by Skills Workflow. - New Expense Items created in Skills Workflow are automatically created in Primavera. - Any change in the Expense Items data is also synched with Primavera. #### Expense Items Data Exchanged Fields that are populated into Primavera: - Oid - Name - CompanyId - ExpenseId - Emission - Due - Employee - Supplier - OtherCreditor - Currency - Exchange - TotalValue - PaymentCondition - ExpenseItemId - CommercialClientName - ProjectId - ProjectBillingClient - ProjectBeginDate - ProjectEndDate - ProjectNumber - ProjectName - ProjectSequence - ProjectYear - ContractNumber - ContractName - ContractSequence - ContractYear - ExpenseItemType - Motive - ValueWithoutVat - VatValue - Vat - VatPercentage - ValueWithVat - CorrectionValue - ExternalId - ExternalName - ExternalItemId - LineNumber - CostCenter - PrimaveraDocumentType - DocumentNumber - ExpenseItemOrder - WorkflowStateId - PreviousWorkflowStateId - KeepOnError #### Purchase Order Item Purchase Orders are sent by Skills Workflow. - New Purchase Orders created in Skills Workflow are automatically created in Primavera. - Any change in the Purchase Orders data is also synched with Primavera. #### Purchase Orders Data Exchanged The fields that are populated into Primavera: - Oid - Name - EstimateId - EstimateHasProjectId - EstimateAccountCode - EstimateAccountName - EstimateAccountBeginDate - EstimateAccountEndDate - EstimateAccountBillingClient - PurchaseOrderId - Supplier - OtherCreditor - Currency - Exchange - TotalValue - PaymentCondition - YourReference - Date - CommercialClientName - ProjectNumber - ProjectName - ProjectSequence - ProjectYear - ContractNumber - ContractName - ContractSequence - ContractYear - PurchaseOrderItemId - Article - Description - Vat - VatPercentage - UnitPrice - Discount - Quantity - ValueWithoutVat - VatValue - ValueWithVat - ExternalId - External - ExternalItemId - LineNumber - EstimateNumber - CostCenter - Billed - CompanyId - PurchaseOrderItemOrder - WorkflowStateId - PreviousWorkflowStateId - KeepOnError #### Supplier Invoice Item Supplier Invoices are sent by Skills Workflow. - New Supplier Invoices created in Skills Workflow are automatically created in Primavera. - Any change in the Supplier Invoices data is also synched with Primavera. #### Supplier Invoices Data Exchanged The fields that will be populated into Primavera: - Oid - Name - SupplierInvoiceId - CompanyId - Emission - Due - Supplier - OtherCreditor - Currency - Exchange - TotalValue - PaymentCondition - SupplierInvoiceItemId - CommercialClientName - ProjectId - ProjectBillingClient - ProjectBeginDate - ProjectEndDate - ProjectNumber - ProjectName - ProjectSequence - ProjectYear - ContractNumber - ContractName - ContractSequence - ContractYear - Article - Description - ValueWithoutVat - VatValue - Vat - VatPercentage - ValueWithVat - ExternalId - External - ExternalItemId - LineNumber - CostCenter - PrimaveraDocumentType - SupplierInvoiceItemOrder - WorkflowStateId - PreviousWorkflowStateId - KeepOnError #### Supplier Note Item Supplier Note Items are sent by Skills Workflow. - New Supplier Noye Items created in Skills Workflow are automatically created in Primavera. - Any change in the Supplier Note Items data is also synched with Primavera. #### Supplier Note Data Exchanged The fields that will be populated into Primavera: - Oid - Name - SupplierNoteId - CompanyId - Emission - Due - Supplier - OtherCreditor - Currency - Exchange - TotalValue - PaymentCondition - SupplierNoteItemId - CommercialClientName - ProjectId - ProjectBillingClient - ProjectBeginDate - ProjectEndDate - ProjectNumber - ProjectName - ProjectSequence - ProjectYear - ContractNumber - ContractName - ContractSequence - ContractYear - Article - Description - ValueWithoutVat - VatValue - Vat - VatPercentage - ValueWithVat - ExternalId - External - ExternalItemId - LineNumber - CostCenter - PrimaveraDocumentType - SupplierNoteItemOrder - WorkflowStateId - PreviousWorkflowStateId - KeepOnError --- ### Conclusion The contents of this document create the foundation for data and process communication methodology between Skills Workflow and Agencies. The current known data and process transfers are contained in this document but more may be created as additional data and process needs are discovered. --- ## Publi URL: https://documentation.skillsworkflow.com/docs/integrations/Publi Summary: Publi is the agency's media-buying system, where media budgets are registered and bought against. ### Description This article describes the integration between **Publi** and `Skills Workflow`. Publi is the agency's media-buying system, where media budgets are registered and bought against. Skills Workflow is where the estimate behind that budget is built and approved with the client. This integration hands the estimate over the moment it is approved. An estimate in Skills Workflow can be a substantial document — client, contract, currency, supplier, and a set of billed lines — and re-keying it into a media system is both slow and the kind of task where a transposed figure is expensive. Here the whole thing is assembled and sent in one step, and the reference Publi assigns is written back onto the estimate so both systems point at the same budget. --- ### Data Exchange Technology The exchange runs over the Publi web service. Skills Workflow logs in with a dedicated user and then submits the estimate. No files and no locally installed application are required. It is **event-driven**: it fires when the estimate reaches the stage that means it is approved for media. Nothing is sent before then. The login is performed **per company** — the division the estimate belongs to determines which Publi company the estimate is registered against, so a group with several media companies posts each one's budgets into the right place. --- ### Data Exchange (From Skills Workflow) **Estimates → Orçamentos (budgets)** When an estimate reaches the **Integrado** stage, it is sent to Publi as a budget, carrying its client, contract, currency, supplier and billed lines. The identifier Publi returns is stored on the estimate, and is the visible sign the hand-off succeeded. An estimate that has already been sent is **not sent again** if it changes stage a second time, so re-triggering does not create a duplicate budget in the media system. --- ### What the Agency Needs to Provide - **A Publi web service address**, plus a dedicated login and password for Skills Workflow. - **Division records carrying their Publi company code**, since the division is what selects the Publi company to log into. - **An *Integrado* stage** on the Estimate document type, since reaching it is what triggers the hand-off. --- ### Good to Know - **Nothing is sent until the estimate is approved.** Moving an estimate between other stages never registers a budget by accident. - **An estimate is only ever sent once.** The integration checks before sending, so a duplicate budget is not created. - **The division decides the Publi company.** If a division is missing its Publi code, the login for that estimate cannot be performed. - The integration is one-way: changing the budget in Publi does not update the estimate in Skills Workflow. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Publi-EstimateWithBills-Integrate | Automation | 1 | Active | Logs into Publi and submits the estimate/bill data | | Publi-Estimate-StageUpdated | Webhook | 1 | Active | Fires the automation when an Estimate moves to "Integrado" | | Publi-EstimateById | Query | 2 | Active | Builds the full estimate+bills payload ("orçamento") sent to Publi | | Publi-EstimateDivisionExternalId | Query | 1 | Active | Looks up the division's external id, used to log into Publi as the right "empresa" | Source: `[Publi] [Integrations] Publi-EstimateWithBills-Integrate v1 (Automation) {Active}.json`, `[Publi] [Integrations] Publi-Estimate-StageUpdated v1 (Webhook) {Active}.json`, `[Publi] [Integrations] Publi-EstimateById v2 (Query) {Active}.json`, `[Publi] [Integrations] Publi-EstimateDivisionExternalId v1 (Query) {Active}.json`. #### How It Works 1. The webhook listens for `StageUpdated` on `Skill.Module.BusinessObjects.Estimate` where `toWorkflowStageName` equals "Integrado", and fires `Publi-EstimateWithBills-Integrate` (matching automation id `ff2184c4-f71b-4640-82ff-e13a0654885e`). 2. The automation reads the `publi-integration` configuration key (Publi host and credentials), then runs `Publi-EstimateDivisionExternalId` to get the division's external id. 3. It logs into Publi (`GET {host}/publiweb/Services/IntegracaoService.svc/Login?usuario=&senha=&empresa=`), a SOAP-style web service, using that division as the "empresa" (company). 4. It runs `Publi-EstimateById`, passing the estimate id and the login token; this query assembles the full estimate — including bills, bill items, supplier, client, contract and currency data — into a single `json` payload representing an "orçamento" (budget) with an `operation` flag. 5. If `operation` is `INCLUSAO` (insert — i.e. not yet sent), it `POST`s the payload to Publi (`.../IntegracaoService.svc/SaveOrcamento`) and writes the returned description back onto the Estimate as its `ExternalId` (`PATCH /api/estimates/{id}`). If the estimate was already integrated, it exits without resending. #### External System Contact Points - Publi web service (host from the `publi-integration` configuration key): `GET .../publiweb/Services/IntegracaoService.svc/Login`, `POST .../publiweb/Services/IntegracaoService.svc/SaveOrcamento`. - Skills Workflow's own analytics/API: named queries `Publi-EstimateDivisionExternalId`, `Publi-EstimateById`; `PATCH /api/estimates/{id}`. #### Configuration - Configuration key **`publi-integration`** — holds the Publi host (`host`), login (`usuario`), and password (`senha`). Values are not part of the export. #### Open Questions - The exact shape and field mapping of the "orçamento" JSON built by `Publi-EstimateById` (beyond the tables it joins — bills, bill items, supplier, client, contract, currency) is not fully determinable without the query's full SQL text. - What "already integrated" (`operation` other than `INCLUSAO`) means for a re-triggered stage change, and whether updates are ever resent, is not determinable from the export. --- ## Reach URL: https://documentation.skillsworkflow.com/docs/integrations/reach Summary: Reach is the agency's HR system. ### Description This article describes the integration between **Reach (SAP SuccessFactors)** and `Skills Workflow`. Reach is the agency's HR system. This integration takes care of user provisioning: the people who exist in HR are the people who exist in Skills Workflow, kept current as they join, move and leave — without HR or IT maintaining a second list. --- ### Data Exchange Technology Data moves as **CSV files over an SFTP server**. The server is set up by the agency, which provides the credentials to Skills Workflow. Files are separated by purpose: - Files carrying data go in the **Data** directory. - Files requesting a process go in the **Process** directory. Every file name identifies who originated it and what it contains, so both sides can tell at a glance whether a file is inbound, outbound, data, a process command, or a result. The exact format is in the technical reference. --- ### What Is Exchanged **User Accounts** — the people record that provisions and maintains users in Skills Workflow. Reach data is captured once per day, and the file is delivered at least once a day, sometimes more. Each delivery contains **only the users whose data changed**, which keeps the files small and the processing quick. Each new file supersedes the information in the previous ones. --- ### What the Agency Needs to Provide - An SFTP server with the **Data** and **Process** directories, and credentials for Skills Workflow. - The Reach user export delivered into the Data directory, following the agreed file naming convention. - Agreement on which identifier links a person across the two systems. --- ### Good to Know - Reach is the source of truth for the people data it sends. Manual changes in Skills Workflow to those fields will be overwritten by the next file. - Files are consumed and removed once processed, regardless of the outcome. - The file name suffix is a timestamp, which determines processing order when several files are waiting — so a delayed delivery still applies in the right sequence. - Because only changed users are sent, a person missing from a file has not been removed; they simply did not change. --- For the file naming rules, CSV templates and field-by-field descriptions, see the **[Technical Reference](./reference)**. --- ## Reach — Technical Reference URL: https://documentation.skillsworkflow.com/docs/integrations/reach/reference Summary: --- Source: [Reach] [Integrations] Users v1 (Automation) {Active}. This page is the interface specification for the Reach integration — file formats, naming conventions and field-by-field mappings. It is written for the team implementing the exchange. For what this integration does and how it is configured, see **[Reach](./)**. ### Description This article describes how to exchange data between Reach (SAP SuccessFactors) and Skills Workflow. --- ### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Reach users integration | Automation | 1 | Active | Scheduled job that reads the AD_UserAccounts CSV from SFTP and provisions/updates/deactivates users | Source: `[Reach] [Integrations] Users v1 (Automation) {Active}.json`. --- ### File Transfer Technology - The .csv files will be transferred via an SFTP server. - The server must be set up by the Agency and credentials must be given to Skills Workflow. - Files pertaining to data transfers are to be placed in the Data directory on the SFTP server. - Files pertaining to process requests are to be placed in the Process directory on the SFTP server. --- ### File Naming Conventions Each filename will have a prefix, body, and suffix. The name will convey information to both Agency and Skills Workflow as to the intent and content of the file as described below. The file name format will be as follows: prefix_body_suffix.csv #### Prefix The filename prefix will consist of two characters. The first character indicates the originator of the file. The second character indicates the type of information contained in the file. First Character - A – Originated by Agency - S – Originated by Skills Workflow Second Character - D – Data - P – Process Command - R – Data/Process Results #### Body The body of the filename is simply used to give a friendly name or to designate specific content. #### Suffix The filename suffix is used to ensure a unique file name and implies a process order when multiple files with the same prefix and body exist. The suffix is simply the date and time relevant to the content of the file in the following format: YYYYMMDDHHmmss. - YYYY – The four character year - MM – The two character month, left padded with a zero when necessary (01-12) - DD – The two character day of the month, left padded with zero when necessary (01-31) - HH – The two character hour, in 24-hour format, left padded with zero when necessary (00-23) - mm – The two character minute, left padded with zero when necessary (00-59) - ss – The two character second, left padded with zero when necessary (00-59) #### File Naming Examples The following are examples of file names. The CSV template details will follow. - AD_UserAccounts_20180815090119.csv – File originated by Agency, containing Users Accounts data to be consumed by Skills Workflow --- ### CSV Templates This section will describe the CSV templates for the currently known exchange processes. The consumer of the CSV files will delete the file from the SFTP server when it has been processed regardless of the process results: success, failure or otherwise. #### User Accounts This will contain the user information requested by Skills Workflow. The frequency will be at least once per day but may be a few times per day. The user data is based on a combination of Reach information. Reach data is only captured once per day. The file will contain the list of users whose data has changed. #### File Name The file name that will always be used for this file: AD_UserAccounts_YYYYMMDDHHmmss.csv where the YYYYMMDDHHmmss suffix indicates the as of date. This overrides any previous files information. #### File Directory This file is to be placed in the Data directory on the SFTP server. #### Template ``` { "users": [ { "companyCode": "[AGENCY CODE]", "divisionid": "[DIVISION CODE]", "departmentid": "[DEPARTMENT CODE]", "userTypologyGroup" : "[JOB CLASSIFICATION DESCRIPTION]", "resourceType":"[BUSINESS TITLE]", "userType":"[Regular/Permananet or Temporary]", "name": "[FIRST NAME] [LAST NAME]", "externalId": "[USER ID]", "externalNumber": "[ADP FILE NUMBER]", "responsible" : "[AX INTEGRATION - TIME APPROVER]", "administrativeResponsible" :"[AX INTEGRATION - TIME APPROVER]", "planningResponsible": "[REPORTS TO USER ID]", "leavesResponsible" : "[AX INTEGRATION - TIME APPROVER]", "workphone": "[WORK PHONE]", "email": "[EMAIL]", "ssoUsername" :"[EMAIL]", "username": "[BUSINESS MAIL ADDRESS BEFORE @]", "weeklyRequiredHours": "[CONTRACTED HOURS]", "hireDate": "[AGENCY ADJUSTED SERVICE DATE]", "expirationDate": "[TERMINATE DATE]", "workLocation" : "[USER'S CITY]", "fslaStatus" : "[OVERTIME - TRUE/FALSE]", "isActive" : "[IS ACTIVE], "employeeClass" : "[Freelancer/Intern]" } ] } ``` --- ### Template Description users – Object that contains a list of users' data, where only the users, where it only contains users who have changed (delta files) - companyCode - The agency's code - divisionid - The user division's code - departmentid - The user department's code - userTypologyGroup - The user's job description (not the code) - Case the group typology does not exist in the system, it will be created. - resourceType - User's business title - Case the resourceType/typology does not exist for the corresponding department in the system, it will be created associated with the typology group - userType - This field should be populated with the value of Regular/Permanent or Temporary field from Reach. The userType must exist in the system so the user can be created with the corresponding userType - name - This field should be populated with the user's first and last name - externalId - The user id from Reach - externalNumber - This field should be populated with the user's ADP file number - responsible - This field should be populated with the userId of "Reports To" user - administrativeResponsible - This field should be populated with the userId of "Reports To" user - planningResponsible - This field should be populated with the userId of the user's resource manager (need to find a field in Reach to fill with this enter this information) - leavesResponsible - This field should be populated with the userId of the user that will approve the leaves (need to find a field in Reach to fill with this enter this information if different from administrativeResponsible) - workphone - The user's work phone - email - The user's e-mail - ssoUsername - The user's e-mail - username - The first part of the user's e-mail (Business mail address before "@") - weeklyRequiredHours - The user's contracted hours - hireDate - This field should be populated with the user hire date (agency adjusted service date) - expirationDate - The termination date on the user's contract - workLocation - Indicates where is the Agency city location where the user is working - fslaStatus - Indicates if the user has the flag Overtime enabled or not - isActive - Indicates if the user is active or inactive - employeeClass - To identify the type of Temporary employee being concatenated with userType - Temporary - Freelancer - Temporary - Intern Additionally to the above, there is another field being managed: - Timesheet Required - Set as True - When the userType is Regular/Permanent - Set as False - When the userType is Temporary --- ### How It Works (Automation Logic) The `Reach users integration` automation (`[Reach] [Integrations] Users v1 (Automation) {Active}.json`) runs daily at 04:00 UTC and drives the whole exchange: 1. Reads the SFTP connection details from the configuration key `SFTP-GSPSF` (`GET /api/configuration-keys/SFTP-GSPSF`). 2. Lists files on the SFTP Data directory and loops over each one found. 3. For each file: downloads it over SFTP, reads it as a header CSV, then loops over every row. 4. For each row (a user record): - Looks the user up in Skills Workflow by `externalId` (`GET /api/users/external?externalId=...`). - If not found and `isActive` is `false`, the row is skipped (no user created for an inactive new hire). - If found and `isActive` is `false`, the user is patched with the expiration date and then deactivated (`PATCH /api/users/{id}`, setting `isActive: false` and renaming `userName`/`SsoUserName` with the `externalId` suffix so the login frees up). - Otherwise the user is created or updated: the department is looked up by `externalId` (`GET /api/companies/{companyId}/departments/external?externalId=...`) and the job typology group/typology are created if missing (`POST /api/usertypologygroups`, `POST /api/usertypologies`) — freelancers (`employeeClass = Freelancer`) get a group name prefixed `FREELANCE `. - The user is created via `POST /api/users`; freelancers are created inactive first and then activated in a second pass. - If `responsible` (manager external ID) is present, the manager is looked up (`GET /api/users/external?externalId=...`) and patched onto the user as `ResponsibleId`, together with `PaidOvertime` from `fslaStatus` and, when present, `CityId` from `workLocation`. - If the manager lookup fails, the user is still created, and the automation result payload notes that it was created without a manager. 5. Once a file's rows are all processed, the file is moved to the SFTP success or failure subfolder (`ftpToPathSuccess` / `ftpToPathFailure`, both read from the same `SFTP-GSPSF` configuration key). The automation only sends error notifications (`sonia@skillsworkflow.com`); it does not notify on success. --- ### External System Contact Points - **SFTP** — host, credentials and paths are not hard-coded; they are all resolved at runtime from the Skills Workflow configuration key `SFTP-GSPSF`. - **Skills Workflow Integration API** (`integration-api-eastus.skillsworkflow.com`) — the automation calls it to read and write user, department and typology data: - `GET /api/users/external?externalId=` - `POST /api/users` - `PATCH /api/users/{id}` - `GET /api/companies/{companyId}/departments/external?externalId=` - `POST /api/usertypologygroups` - `POST /api/usertypologies` - `GET /api/usertypes/name?name=` ### Configuration - Configuration key **`SFTP-GSPSF`** — holds `ftpHostIp`, `ftpUsername`, `ftpPassword`, `ftpPath`, `ftpToPathSuccess`, `ftpToPathFailure` and `fileNameContains`. Its values are not part of the export. - Scheduler — daily, starting 2023-11-16 04:00 UTC; error notifications go to `sonia@skillsworkflow.com`. ### Open Questions - The CSV template above documents `divisionid`, `administrativeResponsible`, `planningResponsible` and `leavesResponsible`, but none of these fields are read anywhere in the exported automation — not determinable from the export whether they are still produced by Reach or simply unused. - The exact matching rule Skills Workflow uses to decide create vs. update (beyond the `externalId` lookup) is not determinable from the export. --- ## Sage URL: https://documentation.skillsworkflow.com/docs/integrations/sage Summary: Sage is where the agency's finance team works. ### Description This article describes the integration between the **Sage** ERP and `Skills Workflow`. Sage is where the agency's finance team works. This integration removes the double entry between the two systems: the master data finance already maintains in Sage — clients, suppliers, VAT, currencies, payment conditions — flows into Skills Workflow so the operational teams book work against the correct records, and the financial documents produced by those teams flow back into Sage for invoicing and payment. Neither side has to retype the other's data, and neither side has to wait for the other to catch up. --- ### Data Exchange Technology The exchange is based on **views**. The ERP is installed locally on the agency's server, and the integration reads and writes through views made available in the system. --- ### What Comes Into Skills Workflow Sage is the source of truth for the financial master data: | Received from Sage | Why it matters | | --- | --- | | Clients | Teams book work against the same client records finance invoices | | Suppliers | Purchase orders and supplier invoices reference real, approved suppliers | | Articles | The billable item catalogue | | VAT | Correct tax rates on every document | | Currency | Multi-currency work is valued consistently in both systems | | Payment Conditions | Payment terms travel with the client | | Expense Item Types | Expenses are classified the way finance expects | | Reversal Reasons | Credit notes carry a reason finance recognises | | Employees | People records stay aligned | New records created in Sage are created automatically in Skills Workflow, and later changes are synchronised. --- ### What Goes Out To Sage The financial documents produced in Skills Workflow are sent to Sage: - Bills - Client Credit Notes - Expenses - Purchase Orders - Supplier Invoices - Supplier Notes Documents are exported at item level, so Sage receives the detail behind each total rather than a single lump sum. --- ### What the Agency Needs to Provide - A Sage installation reachable by the integration, with the required views available. - Confirmation of which companies are in scope. - Agreement on how master data records are identified on both sides, so records match rather than duplicate. --- ### Good to Know - Sage is the source of truth for master data. Changes made manually in Skills Workflow to clients, suppliers, VAT or currencies will be overwritten. - Skills Workflow is the source of truth for the documents it produces. They are created in Skills Workflow and sent onwards, not the other way round. - Records are matched by their external identifier. Changing it manually on either side will cause duplicates. --- For the field-by-field mappings, see the **[Technical Reference](./reference)**. --- ## Sage — Technical Reference URL: https://documentation.skillsworkflow.com/docs/integrations/sage/reference Summary: This is the Documentation of how the Integration between the Sage and Skills Workflow. This page is the interface specification for the Sage integration — file formats, naming conventions and field-by-field mappings. It is written for the team implementing the exchange. For what this integration does and how it is configured, see **[Sage](./)**. ### Description This is the Documentation of how the Integration between the Sage and `Skills Workflow`. This documentation is for Skills Workflow located in the Cloud. --- ### Data Exchange Technology Based on Views. The ERP will be installed locally on a server. The scope of data exchanged on this integration includes: #### From SAGE to Skills Workflow - Master data - Clients - Suppliers - VAT - Currency - Payment Conditions - Articles - Reversal Reasons #### From Skills Workflow to SAGE - Financial Documents - Expenses - Invoices/Bills - Purchases Orders --- ### Data Exchange (To Skills Workflow) This section describes the Data exchanged between systems. Please see the data exchanged. The data is exchanged with Views available in the system. #### Articles Articles are received by Skills Workflow. New Articles created in SAGE are automatically created in Skills Workflow. Any change in the Articles data is also synched with Skills Workflow. #### Articles Data Exchanged Fields that are populated in Skills Workflow are: - CompanyId - CompanyCode - Active - Name - ExternalId - InternalService - VatDeductiblePercentage #### Client Clients are received by Skills Workflow. - New Clients created in SAGE are automatically created in Skills Workflow. - Any change in the Clients data is also synched with Skills Workflow. #### Clients Data Exchanged Fields that are populated in Skills Workflow: - Name - Street - Street2 - City - ZipPostal - StateProvince - Country - TaxPayerNumber - Active - CompanyCode - CompanyId - PaymentConditionExternalId - CurrencyExternalId - ExternalId - ApplyDefaultPaymentCondition - SetFirstPaymentConditionIfExternalIdIsNull - OtherDebtor #### Currency Currencies are received by Skills Workflow. - New Currencies created in SAGE are automatically created in Skills Workflow. - Any change in the Currencies data is also synched with Skills Workflow. #### Currencies Data Exchanged Fields that are populated into Skills: - CompanyId - Active - Name - Symbol - ExternalId - Sell - Buy - Default - Value Round - Vat Round - Price Round #### Employee Employees are received by Skills Workflow. - New Employees created in SAGE are automatically created in Skills Workflow. - Any change in the Employees data is also synched with Skills Workflow. #### Employees Data Exchanged The fields that are populated into Skills Workflow: - Id - Name - Action #### Expense Item Type Expense are received by Skills Workflow. - New Expense Items created in SAGE are automatically created in Skills Workflow. - Any change in the Expense Items data is also synched with Skills Workflow. #### Expense Items Data Exchanged The fields that will be populated into CETA: - Id - Company - Name - Value - Vat - VatDeductiblePercentage - Action #### Payment Conditions Payment Conditions are received by Skills Workflow. - New Payment Conditions are created in SAGE are automatically created in Skills Workflow. - Any change in the Payment Conditions data is also synched with Skills Workflow. #### Payment Conditions Data Exchanged The fields that will be populated into Skills Workflow: - CompanyId - CompanyCode - Active - Name - ExternalId - Days - Discount - ClientDirect - ClientDirectUpdatable - HasTax - HasTaxUpdatable #### Reversal Reason Reversal Reasons are received by Skills Workflow. - New Reversal Reasons are created in SAGE are automatically created in Skills Workflow. - Any change in the Reversal Reasons data is also synched with Skills Workflow. #### Reversal Reasons Data Exchanged The fields that will be populated into Skills Workflow: - CompanyId - CompanyCode - Active - Name - ExternalId #### Supplier Suppliers are received by Skills Workflow. - New Suppliers' created in SAGE are automatically created in Skills Workflow. - Any change in the Suppliers' data is also synched with Skills Workflow. #### Suppliers' Data Exchanged The fields that will be populated into Skills Workflow: - CompanyId - CompanyCode - Active - Name - ExternalId - TaxpayerNumber - Street - Street 2 - City - ZipPostal - StateProvince - OtherCreditor - PaymentConditionExternalId - ApplyDefaultPaymentCondition - CurrencyExternalId - ApplyDefaultCurrency - ApplyDeafultVat #### Vat Vat values are received by Skills Workflow. - New Vat values created in SAGE are automatically created in Skills Workflow. - Any change in the Vat data is also synched with Skills Workflow. #### Vat Data Exchanged The fields that will be populated into Skills Workflow: - CompanyId - CompanyCode - Active - Name - ExternalId - Percentage - Default --- ### Data Exchange (OutBound) This section describes the Data exchanged between systems. Please see the data exchanged. The data is exchanged with Views available in the system. #### Bill Item Bill Items are sent by Skills Workflow. - New Bills Items' created in Skills Workflow are automatically created in SAGE. - Any change in the Bills data is also synched with SAGE. #### Bill Item Data Exchanged Fields that are populated in SAGE: - Oid - Name - CompanyId - EstimateId - EstimateHasProjectId - EstimateAccountCode - EstimateAccountName - EstimateAccountBeginDate - EstimateAccountEndDate - EstimateAccountBillingClient - BillId - BillingClient - OtherDebtor - Currency - Exchange - TotalValue - PaymentCondition - YourReference - Date - Due - CommercialClientName - ProjectNumber - ProjectName - ProjectSequence - ProjectYear - Project - ContractNumber - ContractName - ContractSequence - ContractYear - BillItemId - Article - Description - Vat - VatPercentage - UnitPrice - Discount - Quantity - ValueWithoutVat - VatValue - ValueWithVat - ExternalId - External - ExternalItemId - LineNumber - Remarks - AttentionLine - EstimateNumber - SAGEDocumentType - CostCenter - BillItemOrder - WorkflowStateId - PreviousWorkflowStateId - KeepOnError #### Credit Client Note Credit Client Notes are sent by Skills Workflow. - New Credit Client Notes created in Skills Workflow are automatically created in SAGE. - Any change in the Credit Client Notes data is also synched with SAGE. #### Credit Client Notes Data Exchanged Fields that are populated in SAGE: - Oid - Name - CompanyId - EstimateId - EstimateHasProjectId - EstimateAccountCode - EstimateAccountName - EstimateAccountBeginDate - EstimateAccountEndDate - EstimateAccountBillingClient - ClientCreditNoteId - BillingClient - OtherDebtor - Currency - Exchange - TotalValue - PaymentCondition - YourReference - Date - CommercialClientName - ProjectNumber - ProjectName - ProjectSequence - ProjectYear - Project - ContractNumber - ContractName - ContractSequence - ContractYear - ClientCreditNoteItemId - Article - Description - Vat - VatPercentage - UnitPrice - Discount - Quantity - ValueWithoutVat - VatValue - ValueWithVat - Chargeback - ReversalReason - BillItem - BillName - ExternalId - External - ExternalItemId - LineNumber - EstimateNumber - CostCenter - ClientCreditNoteItemOrder - WorkflowStateId - PreviousWorkflowStateId - BillNames - KeepOnError #### Expense Item Expense Items are sent by Skills Workflow. - New Expense Items created in Skills Workflow are automatically created in SAGE. - Any change in the Expense Items data is also synched with SAGE. #### Expense Items Data Exchanged Fields that are populated into SAGE: - Oid - Name - CompanyId - ExpenseId - Emission - Due - Employee - Supplier - OtherCreditor - Currency - Exchange - TotalValue - PaymentCondition - ExpenseItemId - CommercialClientName - ProjectId - ProjectBillingClient - ProjectBeginDate - ProjectEndDate - ProjectNumber - ProjectName - ProjectSequence - ProjectYear - ContractNumber - ContractName - ContractSequence - ContractYear - ExpenseItemType - Motive - ValueWithoutVat - VatValue - Vat - VatPercentage - ValueWithVat - CorrectionValue - ExternalId - ExternalName - ExternalItemId - LineNumber - CostCenter - SAGEDocumentType - DocumentNumber - ExpenseItemOrder - WorkflowStateId - PreviousWorkflowStateId - KeepOnError #### Purchase Order Item Purchase Orders are sent by Skills Workflow. New Purchase Orders created in Skills Workflow are automatically created in SAGE. Any change in the Purchase Orders data is also synched with SAGE. #### Purchase Orders Data Exchanged The fields that are populated into SAGE: - Oid - Name - EstimateId - EstimateHasProjectId - EstimateAccountCode - EstimateAccountName - EstimateAccountBeginDate - EstimateAccountEndDate - EstimateAccountBillingClient - PurchaseOrderId - Supplier - OtherCreditor - Currency - Exchange - TotalValue - PaymentCondition - YourReference - Date - CommercialClientName - ProjectNumber - ProjectName - ProjectSequence - ProjectYear - ContractNumber - ContractName - ContractSequence - ContractYear - PurchaseOrderItemId - Article - Description - Vat - VatPercentage - UnitPrice - Discount - Quantity - ValueWithoutVat - VatValue - ValueWithVat - ExternalId - External - ExternalItemId - LineNumber - EstimateNumber - CostCenter - Billed - CompanyId - PurchaseOrderItemOrder - WorkflowStateId - PreviousWorkflowStateId - KeepOnError #### Supplier Invoice Item Supplier Invoices are sent by Skills Workflow. - New Supplier Invoices created in Skills Workflow are automatically created in SAGE. - Any change in the Supplier Invoices data is also synched with SAGE. #### Supplier Invoices Data Exchanged The fields that will be populated into SAGE: - Oid - Name - SupplierInvoiceId - CompanyId - Emission - Due - Supplier - OtherCreditor - Currency - Exchange - TotalValue - PaymentCondition - SupplierInvoiceItemId - CommercialClientName - ProjectId - ProjectBillingClient - ProjectBeginDate - ProjectEndDate - ProjectNumber - ProjectName - ProjectSequence - ProjectYear - ContractNumber - ContractName - ContractSequence - ContractYear - Article - Description - ValueWithoutVat - VatValue - Vat - VatPercentage - ValueWithVat - ExternalId - External - ExternalItemId - LineNumber - CostCenter - SAGEDocumentType - SupplierInvoiceItemOrder - WorkflowStateId - PreviousWorkflowStateId - KeepOnError #### Supplier Note Item Supplier Note Items are sent by Skills Workflow. - New Supplier Noye Items created in Skills Workflow are automatically created in SAGE. - Any change in the Supplier Note Items data is also synched with SAGE. #### Supplier Note Data Exchanged The fields that will be populated into SAGE: - Oid - Name - SupplierNoteId - CompanyId - Emission - Due - Supplier - OtherCreditor - Currency - Exchange - TotalValue - PaymentCondition - SupplierNoteItemId - CommercialClientName - ProjectId - ProjectBillingClient - ProjectBeginDate - ProjectEndDate - ProjectNumber - ProjectName - ProjectSequence - ProjectYear - ContractNumber - ContractName - ContractSequence - ContractYear - Article - Description - ValueWithoutVat - VatValue - Vat - VatPercentage - ValueWithVat - ExternalId - External - ExternalItemId - LineNumber - CostCenter - SAGEDocumentType - SupplierNoteItemOrder - WorkflowStateId - PreviousWorkflowStateId - KeepOnError --- ### Conclusion The contents of this document create the foundation for data and process communication methodology between Skills Workflow and Agencies. The current known data and process transfers are contained in this document but more may be created as additional data and process needs are discovered. --- ## Siphon URL: https://documentation.skillsworkflow.com/docs/integrations/Siphon Summary: When a client approves a brief, the assets that brief covers usually need to be made available to someone outside Skills Workflow — a production partner, a… ### Description This article describes the **Siphon** integration in `Skills Workflow`. When a client approves a brief, the assets that brief covers usually need to be made available to someone outside Skills Workflow — a production partner, a media owner, or the client themselves. Producing that shareable link is a small task, but it is a manual one, and it sits directly in the path between approval and the work actually starting. This integration removes that step. The moment a brief is marked **Client Approved**, its details are handed to the external system that produces the shared link, without anyone having to ask for it. The value is in the timing rather than the volume: approval and availability become the same event, so nothing waits on someone remembering to generate a link. --- ### Data Exchange Technology The exchange is a **single outbound call over the web**, authenticated with an access key held in Skills Workflow's configuration. No files and no locally installed application are required. It is **event-driven** — it fires on the approval itself, and nothing is sent at any other time. Both the destination address and the key are configured rather than fixed, so the same mechanism can point at whichever service the agency uses to produce the links. --- ### Data Exchange (From Skills Workflow) **Approved briefs → a link request** When a Request reaches the **Client Approved** stage, the following is sent: | Sent | Meaning | | --- | --- | | Brief identifier and name | Which brief was approved | | Client name | Who approved it | | Brand name and number | What it is for | --- ### What the Agency Needs to Provide - **The destination address** of the service that produces the shared links, plus the access key for Skills Workflow to authenticate with. - **A *Client Approved* stage** on the Request document type, since reaching it is what triggers the hand-off. --- ### Good to Know - **Only client approval triggers it.** A brief moving between any other stages sends nothing. - **Skills Workflow does not hold the link.** It hands over the brief's details; producing and distributing the link is the receiving system's job, so the link itself appears there rather than on the Request. - The integration is one-way and fire-and-forget — there is no response written back onto the brief. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Swivle - Request brief shared link | Automation | 1 | Active | Forwards the approved brief's data to an external webhook so a shared link can be created | | Request to create Brief shared link | Webhook | 1 | Active | Fires the automation when a Request's stage changes to "Client Approved" | | GetBriefData | Query | 1 | Active | Looks up the brief's id, name, client name, brand name and brand number | Source: `[Siphon] [Integrations] Swivle - Request brief shared link v1 (Automation) {Active}.json`, `[Siphon] [Integrations] Request to create Brief shared link v1 (Webhook) {Active}.json`, `[Siphon] [Integrations] GetBriefData v1 (Query) {Active}.json`. #### How It Works 1. The webhook listens for `StageUpdated` events on `Skill.Module.BusinessObjects.Request` where `toWorkflowStageName` equals "Client Approved", and calls the `Swivle - Request brief shared link` automation (id `9fa9842e-26ec-4807-9d1b-da1471e8020c`). 2. The automation reads the `Siphon` configuration key (which holds a target URL and an auth key), then runs the `GetBriefData` query (`POST /api/v3/analytics/named-query/GetBriefData/execute`) with the Request's id, returning `briefId`, `briefName`, `clientName`, `brandName` and `brandNumber`. 3. It `POST`s that data as JSON to the URL stored in the configuration key (`Authorization: Bearer `), then exits. The automation's name (`Swivle - Request brief shared link`) indicates the receiving endpoint is expected to create a shared link in Swivle, the agency's DAM (see the [Swivle](./swivle) integration) — but the export only shows the outbound call to a generically-named `Siphon` webhook target, not the receiving side. #### External System Contact Points - Outbound webhook: URL and bearer key are both read from the `Siphon` configuration key at runtime, not hard-coded — the actual endpoint is not part of the export. - Skills Workflow's own analytics API: `POST /api/v3/analytics/named-query/GetBriefData/execute`. #### Configuration - Configuration key **`Siphon`** — holds `webhooksUrl` (the outbound target) and `key` (bearer token). Values are not part of the export. #### Open Questions - What system actually receives the "Siphon" webhook, and what it does with the brief data, is not determinable from the export — the automation's name suggests it results in a Swivle shared link, but this is not confirmed by any Swivle-side file. --- ## Sitecore URL: https://documentation.skillsworkflow.com/docs/integrations/Sitecore Summary: These are not a background data exchange — they are two working screens built into the Request itself, for teams whose job is placing advertising orders… ### Description This article describes the **Assets & Orders** and **Content Library** workspaces in `Skills Workflow`. These are not a background data exchange — they are two working screens built into the Request itself, for teams whose job is placing advertising orders against publications and re-using approved assets to do it. - **Assets & Orders** is where an advertising order is specified: the order type (print, video, digital banner or master assets), the publication and section it runs in, and the exact production specification that section demands — ad size, bleed and safety margins. It also controls when the brief can be submitted. - **Content Library** is where the assets to fulfil that order are found: a searchable, filterable library of the organisation's approved assets, browsed as a grid or a list, collected into a cart, and added to the Request as order items. The value is that the whole order is specified in one place. Traditionally the specification lives in a publication's spec sheet, the assets live in a digital asset management system, and the order lives in a third place — so producing one order means three tools and a lot of copying. Here the specification, the asset selection and the order are the same screen, and what is selected becomes the Request's own line items directly. --- ### Data Exchange Technology Both workspaces are **interactive panels inside the Request** — they run when someone opens the Request, not on a schedule. The **Assets & Orders** panel is served entirely from Skills Workflow's own data: publications, sections, specifications and the Request's own items. The **Content Library** panel reaches out to the organisation's asset library to search, to fetch the available filters, and to resolve users. Assets selected there are written back as Request items through Skills Workflow's own API. --- ### What the User Sees **Assets & Orders** - Choose the order type: Print, Video, Digital Banner, Master Assets — or view all. - See the publication's delivery details and the section's production specification (ad size, bleed height and width, safety height and width). - Add orders to the brief, and submit it. The **Submit** control is only enabled when there is something new to submit — it compares when the Request was last changed against when its status last changed, so a brief cannot be submitted twice over with nothing altered in between. **Content Library** - Search the asset library by free text, and narrow with filters, including market and language. - Switch between a tile view and a list view, sort, and page through the results. - Add assets to a cart, then add the cart's contents to the Request as order items. --- ### What the Agency Needs to Provide - **A connection to the organisation's asset library**, configured so the library can be searched and its filters listed. - **Publications and sections** registered in Skills Workflow with their production specifications, since the order screen presents these. - **The order types** the agency uses, mapped to the panel's options. --- ### Good to Know - **These are screens, not a sync.** Nothing happens in the background; the panels act when someone uses them. - **What is selected becomes Request items.** Removing an asset from the cart removes the corresponding line. - **The Submit control is deliberately conditional** — if it appears disabled, it usually means nothing has changed since the last submission. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Assets & Orders | Workspace | 43 | Active | Order-type selection and brief submission panel for a Request, backed entirely by Skills Workflow's own database | | Content Library | Workspace | 2 | Active | Asset search/browse/cart panel embedded in a Request | Source: `[Sitecore] [Integrations] Assets & Orders v43 (Workspace) {Active}.json`, `[Sitecore] [Integrations] Content Library v2 (Workspace) {Active}.json`. #### How It Works **Assets & Orders** — every data source is plain SQL against Skills Workflow's own tables, no external calls: - `request-items` / `request-detail` — the Request's items and order details (language, market, sizes, dates), including custom fields `Zonza Reference` / `Zonza 5 ID` (see Open Questions). - `submit-button-status` — compares the latest modification time on the Request/RequestDetail against the latest status-change `Post`, to decide whether the Submit button should be enabled (there's unsaved changes since the last submission). - `publication-data` / `section-data` — publication delivery details and section specs (bleed/safety sizes, ad size) used to lay out the order. - `deliverable-userfields` — the allowed "Media Type" values for a Deliverable. **Content Library** — a dashboard of 12 UI components (search, filters, tile/list views, cart) whose `assets`, `filters` and `users` data sources are inline JavaScript calling three Skills Workflow integration-workflow automations by id (none included in this export): - `integration-workflows/7f03ffb3-8a37-45b4-951a-f8369e98ad50/execute` — asset search. - `integration-workflows/24737319-db17-4145-b9db-a01013f1e5fa/execute` — filter list. - `integration-workflows/352a1423-6d00-4ac1-9045-ecf20d510763/execute` — user list; its JavaScript names the response variable `zonzaResult`. Adding/removing items uses Skills Workflow's own API (`POST`/`DELETE v3/request-items`), same pattern as the [Swivle](./swivle) Content Library. #### External System Contact Points - Three Skills Workflow integration-workflow automations (ids above) are the actual bridge to the external asset library. **None are included in this export.** - Skills Workflow's own API: `POST /v3/request-items`, `DELETE /v3/request-items`. #### Configuration - Not determinable from the export — the asset library's endpoint, credentials and field mapping live inside the three referenced automations, none of which are part of this export. #### Open Questions - **This Workspace is functionally identical to the [Swivle](./swivle) `Content Library` Workspace** — both call the same automation ids `7f03ffb3-8a37-45b4-951a-f8369e98ad50` and `24737319-db17-4145-b9db-a01013f1e5fa`, and this version additionally calls `352a1423-6d00-4ac1-9045-ecf20d510763` for a user list whose result is internally named `zonzaResult` in the JavaScript. This is a concrete lead that the DAM behind "Swivle"/"Sitecore" may in fact be **Zonza** — see the note added to `docs/integrations/zonza.md`, which currently states no Zonza integration was found in the platform. That note should be revisited against this evidence. - Nothing in either exported file references the Sitecore CMS product (no `sitecore`-domain URL, API, or field). "Sitecore" here is most likely a client/tenant name rather than the CMS product; not determinable from the export. - The three integration-workflow automations that do the real work are not part of this export, so their authentication and the external system(s) they call are not determinable. --- ## SSO Configuration URL: https://documentation.skillsworkflow.com/docs/integrations/single-sign-on-sso Summary: Skills Workflow supports SSO using the SAML 2. Skills Workflow supports SSO using the **SAML 2.0 protocol**. This allows users to authenticate via an external Identity Provider (IdP) such as Okta, OneLogin, or Microsoft Entra. To ensure a successful integration in the **Production environment**, the following conditions must be met: - The Identity Provider must support **SAML 2.0** - A **User Identification Claim** must be agreed upon (preferably **Email**, or alternatively **AD Username**) Currently supported providers include: - [Google Suite](google-suite) - [Microsoft Entra](microsoft-entra) - [Okta](okta) --- ### Configuration Steps 1. Access the system’s SAML metadata at: [https://auth.skillsworkflow.com/saml2/metadata](https://auth.skillsworkflow.com/saml2/metadata) 2. Import this metadata into your Identity Provider. 3. Define the User Identification Claim in the Identity Provider as: `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier` - In most cases, this corresponds to the user's AD UPN (User Principal Name) 4. Export the Identity Provider’s metadata file. 5. Provide this metadata to the Skills Workflow support team so it can be installed in your tenant. 6. Ensure that users are mapped correctly between both systems (AD and Skills Workflow). Skills Workflow **does not support Identity Provider-initiated login**. The login flow must begin on the Skills Workflow platform. To simplify user access, you can create a custom bookmark or button in your Identity Provider dashboard (or internal portal) pointing to: **`https://{tenant-name}.skillsworkflow.com/ssologin`** This ensures the login process starts correctly from the Service Provider side. --- ### Requirements Summary - **SAML 2.0** protocol - **SHA-1** signing algorithm - **Service Provider-initiated login only** --- ### Test Environment Setup SSO can also be configured for the **Test environment** (not to be confused with UAT, which is also a Production environment): - Use your Identity Provider's **preview environment** (e.g. test tenant in Okta, OneLogin, or Office 365) - Export the IdP metadata from that test environment - Provide the metadata to Skills Workflow for installation in your **Test tenant** - The SAML metadata for the Test environment is available at: [https://auth-test.skillsworkflow.com/saml2/metadata](https://auth-test.skillsworkflow.com/saml2/metadata) --- ## Swivle URL: https://documentation.skillsworkflow.com/docs/integrations/Swivle Summary: Swivle is the agency's Digital Asset Management system — the library where approved creative assets live, with the metadata that makes them findable. ### Description This article describes the integration between **Swivle** and `Skills Workflow`. Swivle is the agency's Digital Asset Management system — the library where approved creative assets live, with the metadata that makes them findable. Skills Workflow is where the work that uses those assets is requested and delivered. This integration brings the library **inside the Request**. Rather than a background sync, it is a working screen: someone raising or fulfilling a request searches Swivle, filters it, picks the assets they need, and adds them to the Request as line items — without leaving Skills Workflow, and without downloading and re-uploading anything. The value is that the asset never has to be copied to be used. The library stays the single source of the asset and its metadata; Skills Workflow references it. That means no second copy drifting out of date, no ambiguity about which version was used, and no context-switching for the person doing the work. --- ### Data Exchange Technology The Content Library is an **interactive panel inside the Request** — it runs when someone opens the Request, not on a schedule. When they search or filter, Skills Workflow queries Swivle live and presents the results. Assets they select are written back as Request items through Skills Workflow's own API. Nothing is copied into Skills Workflow beyond the reference and the metadata needed to display it. --- ### What the User Sees - **Search** the library by free text, and narrow the results with filters drawn from Swivle's own metadata — including market and language. - **Browse** results as tiles or as a list, sort them, and page through them. - **Inspect** each asset's details: asset type, file name and format, creation date, dimensions, resolution, orientation, touch point, channel, status, retailer, brand and reference, plus who imported and last modified it. - **Collect** assets into a cart, then add the cart's contents to the Request as items. Supporting files are hidden by default, so the results show the assets people actually mean rather than every artefact behind them. --- ### What the Agency Needs to Provide - **A Swivle account with API access**, and the connection configured in Skills Workflow. - **Agreement on which Swivle metadata fields** should be shown as columns and offered as filters. --- ### Good to Know - **This is a screen, not a sync.** No assets are imported into Skills Workflow in the background; the library is queried live when someone uses it. - **Adding an asset creates a Request item**, which is what carries the reference forward into the work. - **The library is the source of truth for the asset.** Metadata shown in Skills Workflow reflects what is in Swivle at that moment. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Content Library | Workspace | 3 | Active | Dashboard panel embedded in a Request: search/browse Swivle assets and add them as request items | Source: `[Swivle] [Integrations] Content Library v3 (Workspace) {Active}.json`. #### How It Works The Workspace is a dashboard of 12 UI components (search box, filters, tile/list views, cart, sorter, pagination, etc.) bound to a `DataSourceConfiguration` with five data sources: - **`assets`** — the DAM search itself. Its `main` data source is inline JavaScript that calls `SW.executeAPI('POST', 'integration-workflows/7f03ffb3-8a37-45b4-951a-f8369e98ad50/execute', ...)`, passing the free-text search, pagination and any chosen filters, and maps the DAM's raw asset metadata (fields such as `cf_assetType`, `filename`, `dimension`, `cf_touchPoint`, `cf_channels`, `status`, `cf_retailers`, `cf_brand`, `thumbnailUrl`, `previewUrl`, `originalUrl`) into the grid's columns. - **`filters`** — populates the filter list via a second automation, `integration-workflows/24737319-db17-4145-b9db-a01013f1e5fa/execute` (called with body `"GetFilters"`). - **`request-items`** — SQL against Skills Workflow's own database (`RequestItem` / `RequestItem_Userfields`) to show what's already been added to the current Request, including fields `Zonza 4 ID`, `Zonza 5 ID` and `Zonza Reference`. - **`markets`** / **`languages`** — plain SQL lookups (`Market`, `Idiom` tables). - Adding/removing cart items calls Skills Workflow's own API directly: `POST v3/request-items` to add, `DELETE v3/request-items` (bulk or single) to remove. #### External System Contact Points - Two Skills Workflow **integration-workflow automations** (ids `7f03ffb3-8a37-45b4-951a-f8369e98ad50` for asset search and `24737319-db17-4145-b9db-a01013f1e5fa` for filters) are the actual bridge to Swivle. **Neither is included in this export** — this Workspace file only shows that the dashboard calls them by id; how they authenticate to Swivle and shape the request is not determinable from the export. - Skills Workflow's own API: `POST /v3/request-items`, `DELETE /v3/request-items`. #### Configuration - Not determinable from the export — the DAM endpoint, credentials and asset-field mapping all live inside the two referenced automations, which aren't part of this export. #### Open Questions - The two automations the Workspace depends on (`7f03ffb3-8a37-45b4-951a-f8369e98ad50`, `24737319-db17-4145-b9db-a01013f1e5fa`) were not part of this export, so the actual Swivle API calls, authentication and error handling are not determinable. - **This Workspace is functionally identical to the [Sitecore](./sitecore) `Content Library` Workspace** — both call the same two automation ids above. The Sitecore version additionally calls a third automation (`352a1423-6d00-4ac1-9045-ecf20d510763`) whose response it internally names `zonzaResult`, and the `Zonza 4 ID` / `Zonza 5 ID` / `Zonza Reference` fields queried alongside the request items here reinforce that lead. See the note added to `docs/integrations/zonza.md`, which currently states no Zonza integration was found — that note should be revisited against this evidence. --- ## Timely URL: https://documentation.skillsworkflow.com/docs/integrations/Timely Summary: Timely is where people actually record their hours — a lightweight, pleasant time tracker that teams will genuinely use. ### Description This article describes the integration between **Timely** and `Skills Workflow`. Timely is where people actually record their hours — a lightweight, pleasant time tracker that teams will genuinely use. Skills Workflow is where those hours have to end up, because that is where cost, capacity, utilisation and billing are calculated. This integration lets the agency have both: people track time in the tool they like, and the platform gets the time data it needs, without anyone entering the same hours twice or exporting spreadsheets at month end. It works in both directions, because each side owns part of the picture: - **Out to Timely** — the clients and projects people need to track time against, and who is assigned to them, are pushed automatically. Nobody has to maintain a project list in two places, and time can never be logged against a project that does not exist. - **In from Timely** — the hours themselves become timesheets in Skills Workflow, and Timely's labels become work types, so the time arrives already categorised. The point is that time capture stops being an administrative chore. The tracker stays populated on its own, and the hours flow back without a monthly reconciliation. --- ### Data Exchange Technology The exchange runs over the Timely web API, authenticated with the agency's own Timely application using OAuth. No files and no locally installed application are required. It is **event-driven in both directions**: - Creating or activating a client or project in Skills Workflow pushes it to Timely straight away. - Logging, editing or deleting hours in Timely notifies Skills Workflow, which updates the matching timesheet. A bulk load is available for the initial population of clients into Timely. --- ### Data Exchange (From Skills Workflow) | Sent to Timely | When | | --- | --- | | **Clients** | A client is created | | **Projects** | A project becomes Active (from Draft or In Progress) | | **Project team assignments** | Someone is assigned to or removed from a project | Projects are only pushed once they are genuinely active, so drafts do not clutter the tracker. --- ### Data Exchange (To Skills Workflow) | Received from Timely | Becomes in Skills Workflow | | --- | --- | | **Logged hours** | Timesheets, against the matching user and project | | **Labels** | Work types | Editing or deleting an entry in Timely updates or removes the corresponding timesheet, so the two stay aligned rather than only agreeing at the moment of creation. --- ### What the Agency Needs to Provide - **A Timely account**, with an application registered for Skills Workflow to authenticate against, and the account identifier. - **Webhooks configured in Timely** so that logged, edited and deleted hours notify Skills Workflow. - **Agreement on how Timely's labels map** to Skills Workflow work types. --- ### Good to Know - **Projects reach Timely only when Active.** If a project is missing from the tracker, its stage is the first thing to check. - **Users are matched between the two systems by their Timely identifier**, stored on the Skills Workflow user. A person who has not been matched cannot have their hours imported. - **Time flows in, structure flows out.** Timely owns the hours; Skills Workflow owns the clients, projects and who is on them. - Deleting an entry in Timely deletes the timesheet in Skills Workflow — the sync is not append-only. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Timely - Oauth | Automation | 2 | Active | Handles the OAuth token exchange with Timely | | Timely-CreateClient | Automation | 2 | Active | Pushes a new client to Timely | | Timely-OnClientCreated | Webhook | 1 | Active | Fires `Timely-CreateClient` on CommercialClient creation | | Timely-ClientsFirstLoad | Automation | 2 | Active | On-demand bulk push of existing clients to Timely | | Timely-CreateProject | Automation | 3 | Active | Pushes a project to Timely once it becomes Active | | Timely-OnProjectCreated | Webhook | 4 | Active | Fires `Timely-CreateProject` when a Project moves from Draft/InProgress to Active | | Timely-ProjectAssignments | Automation | 1 | Active | Pushes project team assignments to Timely | | Timely-OnAssignmentCreated / (Deleted) | Webhook | 1 | Active | Fire on Assignment created/deleted for a Project | | Timely-SyncWorktypes | Automation | 3 | Active | Pulls Timely's labels into Skills Workflow as Worktypes | | **Legacy per-event timesheet sync** | | | | | | Timely-WebhookReceived | Automation | 4 | Active | Dispatches `hours:created/updated/deleted` events immediately | | Timely-CreateTimesheet | Automation | 10 (highest of 2 versions, both exported) | Active | Creates one timesheet per Timely event, immediately | | Timely-UpdateTimesheet | Automation | 5 | Active | Updates the matching timesheet | | Timely-DeleteTimesheet | Automation | 2 | Active | Deletes the matching timesheet | | Timely-CreateCustomTable | Automation | 1 | Active | Creates the `TimelyTimesheets` custom table this generation relies on | | **"2026" batched timesheet sync** | | | | | | Timely-2026-WebHookReceived | Automation | 2 | Active | Records every incoming Timely event into the `TimelyEvents` custom table | | Timely-2026-HandleEventsByDate | Automation | 2 | **No active trigger** (scheduler `isActive: false`) | Would process a day's stored events into timesheets in bulk | | Timely-2026-CreateTimesheets | Automation | 2 | Active | Creates timesheets from resolved event data, deleting same-day entries first | | Timely-2026-DeleteUserTimesheetsByDay | Automation | 2 | Active | Deletes a user's timesheets for a day, on demand | | Timely-2026-HandleFailedEvent | Automation | 1 | Active | Records an event that failed processing into `TimelyFailedEvents` | | Timely-2026-ProcessFailedEventsByDate | Automation | 1 | Active | Reprocesses failed events for a date | | Timely-2026-CreateCustomTable | Automation | 1 | Active | Creates the `TimelyEvents` / `TimelyFailedEvents` custom tables this generation relies on | | Timely-2026-BulkUpdate | Automation | 1 | Active | On-demand bulk update — body not further inspected | Plus 14 supporting named queries (`Timely-ProjectDetailsById`, `Timely-ProjectIsValid`, `Timely-NewClients`, `Timely-NewWorkTypesByExternalId`, `Timely-GetTimelyTimesheetById`, `-GroupedById`, `-ByUserProjectDay`, `-GetTimelyTimesheetToUpdate`, `Timely-TimesheetDetailsByProject`, `-UpdateTimesheetDetailsByProject`, `Timely-2026-AllEvents-Get`, `-EventsByDate-Get`, `-FailedEvents-Get`, `-FailedEventsByUserAndDate`, `-UserByTimelyId-Get`). Source: files under `[Timely] [Integrations] ...` in the Marketplace export (39 files, 38 distinct components after de-duplicating one attachment pair). This export contains a **legacy** pipeline (`Timely-WebhookReceived` → `Timely-CreateTimesheet`/`UpdateTimesheet`/`DeleteTimesheet`, one timesheet created per event in real time) and a **"2026"** rewrite (`Timely-2026-WebHookReceived` stores every event in a `TimelyEvents` custom table; `Timely-2026-HandleEventsByDate` would process a whole day's events into timesheets in bulk, with failures tracked separately in `TimelyFailedEvents`). Both sets of automations are individually Active, but `Timely-2026-HandleEventsByDate`'s own scheduler is disabled, so — unless something else calls it directly — events land in `TimelyEvents` but are never turned into timesheets by this newer path. It's not determinable from the export whether the legacy pipeline is still the live one (with "2026" only staged for a future cutover) or whether both are live and could double-create timesheets. #### How It Works - **Clients**: `Timely-OnClientCreated` fires `Timely-CreateClient` (confirmed by matching automation id `9c9e17ec-...`), which `POST`s the client to `{api}/{account}/clients` and stores the returned Timely id (`PUT /api/v3/documentUserFieldValues`). `Timely-ClientsFirstLoad` does the same for all existing clients found by `Timely-NewClients`, on demand. - **Projects**: `Timely-OnProjectCreated` fires `Timely-CreateProject` (confirmed by matching automation id `efce2596-...`) when a project reaches Active from Draft or InProgress; it builds the project payload (`Timely-ProjectDetailsById`) and posts it to `{api}/{account}/projects`. - **Assignments**: `Timely-OnAssignmentCreated`/`Deleted` (scoped to Project assignments) drive `Timely-ProjectAssignments`, which validates the project (`Timely-ProjectIsValid`) and updates it in Timely. - **Work types**: `Timely-SyncWorktypes` pulls Timely's labels (`GET {api}/{account}/labels`), resolves new ones (`Timely-NewWorkTypesByExternalId`), and creates them as Skills Workflow Worktypes (`POST /api/Worktypes`) — the only inbound (Timely → Skills Workflow) master-data flow here. - **Timesheets (legacy)**: `Timely-WebhookReceived` dispatches on `hours:created/updated/deleted` (ignoring events tagged `Skills Workflow1`, to avoid reacting to its own writes back to Timely) to `Timely-CreateTimesheet` / `-UpdateTimesheet` / `-DeleteTimesheet`, each of which fetches the event from Timely, builds/matches the timesheet (`Timely-TimesheetDetailsByProject`, `Timely-GetTimelyTimesheetById`), creates/updates/deletes it (`POST`/`PUT`/`DELETE /api/timesheets`), and writes the link into the `TimelyTimesheets` custom table. - **Timesheets ("2026")**: `Timely-2026-WebHookReceived` fetches the event and stores it as a row in `TimelyEvents`. `Timely-2026-HandleEventsByDate` (currently untriggered) would, for a given day, fetch all active Timely users, get each one's events for that day, resolve them against `TimelyEvents`/`Timely-2026-TimesheetDataByEvents`, and hand off to `Timely-2026-CreateTimesheets` (which deletes any existing timesheet for that user/day first, then recreates from the resolved events). Failures are recorded via `Timely-2026-HandleFailedEvent` and can be retried via `Timely-2026-ProcessFailedEventsByDate`. #### External System Contact Points - Timely API (`{api}`/`{account}` from a `Config` configuration key): `GET/POST {account}/clients`, `{account}/projects`, `{account}/labels`, `{account}/users`, `{account}/users/{id}/events`, `{account}/events/{id}`. - Inbound: Timely calls `Timely-WebhookReceived` and `Timely-2026-WebHookReceived`'s endpoints on `hours:*` events. - Skills Workflow's own API/analytics: the named queries above; `POST/PUT/DELETE /api/timesheets`, `POST /api/v3/timesheets`, `GET /api/v3/timesheets/lookup`, `POST /api/Worktypes`, `PUT /api/v3/documentUserFieldValues`, `GET/POST /api/v3/custom-tables/...`. #### Configuration - A `Config` configuration key — holds Timely's `api` base URL and `account`. Values are not part of the export. - Custom tables **`TimelyTimesheets`** (legacy) and **`TimelyEvents`** / **`TimelyFailedEvents`** ("2026") store the integration's own bookkeeping inside Skills Workflow. #### Open Questions - Whether the legacy or the "2026" timesheet pipeline is the one actually in production is not determinable from the export — see the caution above. - `Timely-2026-BulkUpdate` has no inspected body beyond its name; what it bulk-updates isn't determinable from the summary alone. - `Timely - Oauth`'s exact token-refresh mechanics weren't inspected in depth. --- ## TOConline URL: https://documentation.skillsworkflow.com/docs/integrations/toconline Summary: TOConline is the certified online accounting and invoicing platform used by many agencies in Portugal. This page previously described a single bill-to-invoice flow. The exported package (Module `TOC Online`, 32 files / 30 distinct components) is considerably larger: it also issues **client credit notes** and **supplier invoices** to TOConline, and runs a **daily master-data sync** of clients, suppliers, services and taxes. The bill flow below is accurate and unchanged; the "Package Contents" and two new sections cover the rest. ### Description This article describes the integration between **TOConline** and `Skills Workflow`. TOConline is the certified online accounting and invoicing platform used by many agencies in Portugal. This integration closes the last manual step in the billing cycle: once a bill has been approved in Skills Workflow, it is issued as an invoice in TOConline automatically, and the invoice number comes straight back onto the bill. Without it, somebody re-keys every approved bill into the accounting platform — which is slow, error-prone, and leaves the two systems disagreeing about what has actually been invoiced. With it, approval *is* invoicing, and each bill in Skills Workflow carries the TOConline document number that corresponds to it. The same approve-and-send pattern also applies to client credit notes and supplier invoices, and clients, suppliers, services and tax rates are kept in sync with TOConline in the background so the codes bills refer to stay current. --- ### Data Exchange Technology The integration is delivered as a **Marketplace package**, not as a scheduled job. It is event-driven and runs the moment a bill is approved. Skills Workflow authenticates against TOConline using **OAuth2**, with the agency's own application credentials. The credentials are held in a Skills Workflow configuration key, never inside the automation itself. --- ### What Triggers It The integration fires on a single, deliberately narrow condition — a bill moving: | From stage | To stage | | --- | --- | | Under Approval | Integrated | Any other stage change on a bill is ignored. This means a bill is only ever issued once it has cleared approval, and moving a bill between other stages will never invoice it by accident. --- ### What Happens on Each Run 1. The bill's stage change fires the webhook. 2. Skills Workflow authenticates against TOConline. 3. The bill header and its lines are read from Skills Workflow. 4. The customer is read back from TOConline, to pick up the official tax and business name held there. 5. The invoice is created in TOConline. 6. The document number TOConline returns is written onto the bill in Skills Workflow, in the **External** field. Step 6 is what makes the integration auditable: from the bill in Skills Workflow, anyone can see the exact invoice it produced. --- ### What Is Sent **Invoice header** | Sent to TOConline | Taken from | | --- | --- | | Document type | Always issued as an invoice (*FT*) | | Date | The date the bill is integrated | | Customer | The client's **TocOnlineClientCode** | | Customer tax number | The customer record in TOConline | | Customer business name | The customer record in TOConline | | Due date | The bill's due date | | Notes | The bill number, followed by the most recent brief on the document | | External reference | The bill's *Your Reference* field | **Invoice lines** | Sent to TOConline | Taken from | | --- | --- | | Item code | The article's **TocOnlineServiceCode** | | Description | The bill item description | | Quantity | The bill item quantity | | Unit price | The bill item unit price | | Item type | Always sent as *Service* | --- ### What the Agency Needs to Provide **A TOConline application** — client id, client secret, base URL, scope and callback URL, so Skills Workflow can authenticate. These are stored in a Skills Workflow configuration key. **Two user fields, populated:** | Field | On | Holds | | --- | --- | --- | | `TocOnlineClientCode` | Client | The client's customer id in TOConline | | `TocOnlineServiceCode` | Article | The article's item code in TOConline | These are the link between the two systems. A bill for a client without a `TocOnlineClientCode`, or containing an article without a `TocOnlineServiceCode`, cannot be issued — this is the most common cause of failures on this integration, and it is worth checking both are filled in before going live. **Two workflow stages on the Bill document type**, named **Under Approval** and **Integrated**, since the trigger matches on those stages. --- ### Package Contents Install the package from the Marketplace. As exported it contains three financial-document flows (Bill, Client Credit Note, Supplier Invoice), a daily master-data sync, and 21 supporting named queries — not just the bill flow. | Flow | Webhook | Automation | Key Queries | | --- | --- | --- | --- | | Bill → Invoice | Toc Online - On Bill StageChanged (v2) | TocOnline - Integrate Bill (v4) | TocOnline-GetBillById, TocOnline-GetBillItemsById | | Client Credit Note | Toc Online - On Client Credit Note Stage Changed (v2) | TocOnline- Integrate Credit Note (v3) | TocOnline-GetClientCreditNoteById, -ItemsById | | Supplier Invoice | Toc Online - On Supplier Invoice Stage Changed (v1) | Toconline - Integrate Supplier Invoice (v2) | TocOnline-GetSupplierInvoiceById, -ItemsById | | Master data (daily) | — (`TocOnline - Scheduler`, daily) | TocOnline - Clients (v2), Services (v1), Suppliers (v1) | TocOnline-GetBillingClient, -GetCommercialClient, -GetClient, -GetCommercialClientCompany, -GetLastTocOnlineClientCode, -GetArticle, -GetLastTocOnlineServiceCode, -GetSupplier, -GetLastTocOnlineSupplierCode | | Taxes (on demand) | — | TocOnline - Taxes (v3) | TocOnline-GetTaxByExternalIdAndCompany, -GetCompanyByCode | | Expense Item Types (on demand) | — | TocOnline - Expense Item Types (v2) | TocOnline-GetExpenseItemType, -GetLastTocOnlineExpenseItemCode | Plus the configuration key holding the TOConline credentials (aliased `Config` across the automations, holding at least an `api` base URL). --- ### Client Credit Notes and Supplier Invoices The same "approve → integrate" pattern used for bills applies to two more document types: - **Client Credit Notes** — `Toc Online - On Client Credit Note Stage Changed` fires on the same New → Integrated transition as bills. `TocOnline- Integrate Credit Note` builds the credit note and its lines (`TocOnline-GetClientCreditNoteById`, `-ItemsById`) and sends them to TOConline (`POST {api}/api/commercial_sales_documents`, then `POST {api}/api/commercial_sales_document_lines` for the lines, with a `PATCH` variant also present for updates), writing the result back (`PATCH /api/client-credit-notes/{id}`). - **Supplier Invoices** — `Toconline - Integrate Supplier Invoice` builds the invoice (`TocOnline-GetSupplierInvoiceById`, `-ItemsById`) and posts it to TOConline's purchases endpoint (`POST {api}/api/v1/commercial_purchases_documents`, then re-fetches it by id), writing the result back (`PATCH /api/supplier-invoices/{id}`). `Toc Online - On Supplier Invoice Stage Changed`'s two filter conditions **both** check `fromWorkflowStageName` (one against `"Novo"`, one against `"Integrado"`), joined with `AND` — a single event can't have its `fromWorkflowStageName` equal to two different values at once, so as written this filter can never match anything. The second condition was most likely meant to check `toWorkflowStageName` instead. Until that's fixed, this webhook likely never fires. ### Master Data Sync `TocOnline - Clients`, `- Suppliers` and `- Services` each pull their respective list from TOConline (`GET {api}/api/customers`, `/api/suppliers`, `/api/services`), resolve each record against Skills Workflow (assigning the next `TocOnlineClientCode` / `TocOnlineSupplierCode` / `TocOnlineServiceCode` via the matching `GetLastTocOnline...Code` query when creating one), and create/update the corresponding billing client, commercial client, supplier or service — writing the assigned code back via `PUT /api/v3/documentUserFieldValues`. `TocOnline - Scheduler` runs daily and enqueues `Clients`, `Suppliers` and `Services` as background work (confirmed by matching automation ids). `Clients` is additionally exported with its own daily scheduler active, so it currently runs both on its own schedule and via the orchestrator — likely redundant rather than harmful, since it looks up existing records before creating. `TocOnline - Taxes` (pulls `GET {api}/api/taxes`, matches by external id and company, creates/updates `/api/v3/vats`) and `TocOnline - Expense Item Types` (pulls `GET {api}/api/expense_categories`) are on-demand and not part of the daily scheduler chain. --- ### Monitoring and Error Handling Each execution is recorded in the automation's log inside Skills Workflow, including whether it succeeded. If TOConline rejects the invoice, the bill keeps its stage and no document number is written back — so a failure is visible as a bill that reached *Integrated* without an External reference, rather than silently appearing to have been invoiced. --- ### Good to Know - **The invoice date is the date the bill is integrated**, not the bill's own date. Approving a bill late means the invoice carries the later date. - **Every line is issued as a service.** If the agency bills goods as well as services, they will still reach TOConline as service lines. - **Only invoices are issued.** Credit notes and supplier documents are not covered by this package. - The integration is one-way. Changing an invoice in TOConline does not update the bill in Skills Workflow, and re-approving a bill does not re-issue it. --- ## UtilPro URL: https://documentation.skillsworkflow.com/docs/integrations/utilpro Summary: UtilPro is the agency's HR and payroll system. ### Description This article describes the integration between **UtilPro** and `Skills Workflow`. UtilPro is the agency's HR and payroll system. This integration takes care of user provisioning: the people who exist in HR are the people who exist in Skills Workflow, with the department, typology and reporting line HR already maintains — so nobody has to keep a second list current. It also carries the working-time rules — required daily and weekly hours, maximum hours, overtime thresholds — which is what allows timesheets, capacity and resourcing in Skills Workflow to be measured against each person's real contract rather than an assumed standard. --- ### Data Exchange Technology Data moves as **CSV files over an SFTP server**. The server is set up by the agency, which provides the credentials to Skills Workflow. Files are separated by purpose: - Files carrying data go in the **Data** directory. - Files requesting a process go in the **Process** directory. Once a file has been handled it is moved into a **Success** or a **Failure** folder, so it is never processed twice and the agency can always see what happened to a given delivery. --- ### What Is Exchanged **Users** — delivered at least once a day, based on UtilPro data. Each file supersedes the information in the previous ones. The record carries three kinds of information: | Group | What it covers | | --- | --- | | Identity and access | Username, e-mail, SSO account, external identifiers, active status | | Organisation | Company, department, division, typology and typology group, user type, and the person's responsible | | Working time | Maximum hours, required daily and weekly hours, overtime threshold and paid-overtime flag, hire date, start date and expiration date | The **start date** is distinct from the hire date: it is the date from which the person is expected to fill in timesheets in Skills Workflow, which is often later than the day they joined. --- ### What the Agency Needs to Provide - An SFTP server with the **Data** and **Process** directories, and credentials for Skills Workflow. - The UtilPro user export delivered into the Data directory, following the agreed file naming convention. - Agreement on which identifiers link a person, department and typology across the two systems. --- ### Good to Know - UtilPro is the source of truth for the people data it sends. Manual changes in Skills Workflow to those fields will be overwritten by the next file. - The file name suffix is a timestamp, which determines processing order when several files are waiting. - A file that fails is moved to the **Failure** folder and can be corrected and re-delivered. --- For the file naming rules, CSV template and field-by-field descriptions, see the **[Technical Reference](./reference)**. --- ## UtilPro — Technical Reference URL: https://documentation.skillsworkflow.com/docs/integrations/utilpro/reference Summary: The CSV files are transferred via an SFTP server. This page is the interface specification for the UtilPro integration — file formats, naming conventions and field-by-field mappings. It is written for the team implementing the exchange. For what this integration does and how it is configured, see **[UtilPro](./)**. ### File Transfer Technology The CSV files are transferred via an SFTP server. The server must be set up by the Agency and credentials must be given to Skills Workflow. Files pertaining to data transfers should be placed in the Data directory on the SFTP server. Files pertaining to process requests should be placed in the Process directory on the SFTP server. --- ### File Naming Conventions Each CSV filename will have a body and suffix. The name will convey information to both Agency and Skills Workflow as to the intent and content of the file as described below. The file name format will be as follows: body_suffix.csv #### Body The body of the filename is simply used to give a friendly name or to designate specific content. #### Suffix The filename suffix is used to ensure a unique file name and implies a process order when multiple files with the same prefix and body exist. The suffix is simply the date and time relevant to the content of the file in the following format: YYYYMMDDHHmmss. YYYY – The four character year MM – The two character month, left padded with a zero when necessary (01-12) DD – The two character day of the month, left padded with zero when necessary (01-31) HH – The two character hour, in 24 hour format, left padded with zero when necessary (00-23) mm – The two character minute, left padded with zero when necessary (00-59) ss – The two character second, left padded with zero when necessary (00-59) #### File Naming Examples The following are examples of file names. - Users_20180815090119.csv – File originated by Agency, containing Users data to be consumed by Skills Workflow. --- ### CSV Templates This section will describe the CSV templates for the currently known exchange processes. The consumer of the CSV files will move the file to the "Success" folder from the SFTP server when it has been processed successfully and to "Failure" folder when the process result fails. --- ### Users #### User File This will contain the user information requested by Skills Workflow. The frequency will be at least once per day. The user data is based on UltiPro information. #### File Name The file name that will always be used for this file: Users_YYYYMMDDHHmmss.csv where the YYYYMMDDHHmmss suffix indicates the as of date. This overrides any previous files information. #### File Directory This file is to be placed in the Data directory on the SFTP server. #### Template Template Description - UserName - The user's username - FirstName.LastName - John.Doe - ExternalId - The unique identifier to identify the users between systems - ExternalNumber - The ERP users number - CompanyCode - The code that identifies the company/agency - CompanyName - The name of the company/agency - EmployeeExternalId - The unique identifier to identify the users from ERP system - DepartmentExternalId - The unique identifier to identify the user's department between systems - DepartmentName - The user's department name - DivisionName - The division where the user's department belong - TypologyName - The user's typology e.g. Creative, Account, Manager, others... - TypoloyExternalId - The unique identifier to identify the user's typology between systems - TypologyGroupName - The name of the group that the user's typology is included - UserTypeId - The current user type of the user - Full-Time, Part-Time, other - SsoUserName - The user's AD SAM Account Name - Mail - The user's e-mail for communication - IsActive - Users state, if it is active (1) or inactive(0) - MaximumHours - The maximum of hours that users can work per day - HireDate - The user's hire date - StartDate - The user's start date to fill in timesheets in Skills Workflow - ExpirationDate - The user's expiration date - RequiredHours - The Minimum Hours required per day - RequiredWeeklyHours - The Minimum Hours required per week - WeeklyOvertimeThresholdHours - - PaidOvertime - - Phone - The user's phone number - ResponsibleId - The responsible's external id of the user --- ## VBD URL: https://documentation.skillsworkflow.com/docs/integrations/vbd Summary: VBD is where the agency's jobs are opened commercially — a client is registered, a job is numbered, and a campaign is attached to it. This page previously described VBD as a read-only endpoint that **Skills Workflow publishes** for an external consumer to pull from ("Out"). The exported components (Module `SQL Server` in the Marketplace export, all named `VBD - ...`) show the opposite: Skills Workflow **polls an external VBD endpoint** every few minutes and creates clients and projects from what it returns ("In"). Every exported automation reads from `{host}/vbd-skills/client-jobs?since=...&token=...` (a configuration key named `VBD-Integration`) and writes into Skills Workflow via `/api/v3/commercial-clients`, `/api/v3/billing-clients` and `/api/v3/projects` — never the other way around. The previous "publishes a secured endpoint" description is not supported by anything in this export; it has been replaced below. If a separate, genuinely outbound VBD publishing service also exists, it wasn't part of this export. ### Description This article describes the integration between **VBD** and `Skills Workflow`. VBD is where the agency's jobs are opened commercially — a client is registered, a job is numbered, and a campaign is attached to it. Skills Workflow is where that job is then planned, staffed and delivered. This integration removes the set-up step in between. Rather than someone reading the day's new jobs in VBD and creating the matching client and project by hand, the client and the project appear on their own, carrying the job number, campaign, category, owner and cost centre that VBD already holds. The benefit is speed and fidelity at the same time. Work can start almost immediately after it is opened commercially, and the project carries VBD's own reference data rather than a re-typed approximation of it — so the two systems agree on which job is which from the outset. --- ### Data Exchange Technology The exchange runs over the VBD web service, using an address and access token configured by the agency. Skills Workflow polls VBD; VBD does not need to call Skills Workflow, and no files or locally installed application are required. The integration runs on a **short cycle** — it checks for new jobs every few minutes — so a job opened in VBD appears in Skills Workflow within minutes rather than overnight. The exchange is **one-way**: VBD is the source of truth for the client and the job, and Skills Workflow follows it. --- ### Data Exchange (To Skills Workflow) Each record VBD returns carries both the client and the job, and both are created if they do not already exist. **Clients** | Received from VBD | Becomes in Skills Workflow | | --- | --- | | Tax identification | The client's tax number | | Registered legal name | Billing client | | Trading name | Commercial client | | Client code | The client's external reference | The commercial client, the billing client and the link between them and the company are all created together, so the client arrives usable rather than half-formed. **Jobs → Projects** | Received from VBD | Becomes in Skills Workflow | | --- | --- | | Job number | Project number | | Campaign | Project name | | Opening date and time | Project start | | Job category | The project's classification | | Job owner | The project owner | | Competitive-pitch indicator | Recorded on the project | Once created, the project is automatically moved to its first available stage, so it arrives ready to work on. --- ### What the Agency Needs to Provide - **A VBD service address and access token** for Skills Workflow to authenticate with. - **Confirmation of which project classification** corresponds to each VBD job category. - **A workflow on the Project document type** with a valid opening transition, since new projects are moved to their first stage automatically. --- ### Good to Know - **Existing clients and projects are reused, not duplicated.** The integration checks whether each already exists before creating anything, so the same job appearing in consecutive polls does not produce a second project. - **The client is created from the job.** There is no separate client feed — a client arrives the first time a job is opened for them. - The integration is one-way: renaming or re-classifying a project in Skills Workflow does not change the job in VBD. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | VBD - Clients and Projects | Automation | 3 | Active | Current scheduler: polls VBD every 5 minutes, delegates creation to `VBD - Create Client` / `VBD - Create Project` | | VBD - Create Client | Automation | 3 | Active | Creates (or reuses) the commercial/billing client for one VBD record | | VBD - Create Project | Automation | 3 | Active | Creates the project and moves it to its first available stage | | VBD - Daily Clients and Project Creation | Automation | 2 | Active | Older, self-contained version of the same flow — polls every 4 minutes and creates clients/projects inline, without delegating | | VBD-GetClient | Query | 4 | Active | Checks whether a commercial client already exists for the incoming record | | VBD-GetProject | Query | 4 | Active | Checks whether a project already exists for the incoming record | Source: `[SQL Server] [Integrations] VBD - Clients and Projects v3 (Automation) {Active}.json`, `[SQL Server] [Integrations] VBD - Create Client v3 (Automation) {Active}.json`, `[SQL Server] [Integrations] VBD - Create Project v3 (Automation) {Active}.json`, `[SQL Server] [Integrations] Daily Job Creation v2 (Automation) {Active}.json` (component name `VBD - Daily Clients and Project Creation`), `[SQL Server] [Integrations] Get Client v4 (Query) {Active}.json`, `[SQL Server] [Integrations] Get Project v4 (Query) {Active}.json`. **Both the v2 monolithic automation and the v3 scheduler + Create Client/Create Project split are Active at once**, each on its own few-minutes schedule, pulling the same feed. Each path checks for an existing client/project before creating one, so this looks safe from duplicates, but running two overlapping schedulers against the same external feed is redundant — see Open Questions. #### How It Works 1. Every 4–5 minutes, the scheduler (`VBD - Daily Clients and Project Creation` or `VBD - Clients and Projects`) reads the `VBD-Integration` configuration key and calls `GET {host}/vbd-skills/client-jobs?since=&token=` on the external VBD system. 2. For each record returned (fields include `CNPJ_CLIENTE`, `RAZAO_SOCIAL`, `NM_FANTASIA`, `COD_CLIENTE`, `NR_JOB`, `DT_INCLUSAO`, `HORA_INCLUSAO`, `STATUS_JOB`, `CATEGORIA_JOB`, `CAMPANHA_JOB`, `RESPONSAVEL_JOB`, `CONCORRENCIA` — Brazilian-Portuguese fields for client tax id, legal name, trade name, client code, job number, creation date/time, status, category, campaign, owner and a competitive-pitch flag): - `VBD-GetClient` checks whether the client already exists; if not, `VBD - Create Client` creates it (`POST /api/v3/commercial-clients`, `POST /api/v3/billing-clients`, then links them via `POST /api/v3/commercial-clients/{id}/billing-clients`). - `VBD-GetProject` checks whether the project already exists; if not, `VBD - Create Project` creates it (`POST /api/v3/projects`), looks up its first available workflow transition (`GET /api/workflowStateTransitions?...`), and applies it (`POST /api/posts`) — the same "create then move to first stage" pattern seen in the [7Log](./7log) and [Automations](./automations) integrations. 3. In the v3 path, the scheduler enqueues `VBD - Create Client` and `VBD - Create Project` as background work (30-second wait) rather than running them inline. #### External System Contact Points - External VBD endpoint: `GET {host}/vbd-skills/client-jobs?since=&token=`, host and token from the `VBD-Integration` configuration key. - Skills Workflow's own API: `POST /api/v3/commercial-clients`, `POST /api/v3/billing-clients`, `POST /api/v3/commercial-clients/{id}/billing-clients`, `POST /api/v3/projects`, `GET /api/workflowStateTransitions`, `POST /api/posts`; named queries `VBD-GetClient`, `VBD-GetProject`. #### Configuration - Configuration key **`VBD-Integration`** — holds `host` (the external VBD endpoint) and `token`. Values are not part of the export. #### Open Questions - Two schedulers (`VBD - Daily Clients and Project Creation` v2 and `VBD - Clients and Projects` v3, the latter split into `Create Client`/`Create Project`) are both Active and pulling the same feed on overlapping cadences — not determinable whether v2 is meant to have been retired and simply wasn't deactivated, or whether both are intentionally kept running. - Whether a genuinely outbound "Skills Workflow publishes a VBD endpoint" service (as this page previously described) exists anywhere is not determinable from this export — nothing in the exported files does that. --- ## VBS URL: https://documentation.skillsworkflow.com/docs/integrations/vbs Summary: The integration between VBS and Skills Workflow: what it covers and how it is configured. ### Description This article describes the integration between **VBS** and `Skills Workflow`. VBS is the agency's ERP. This is the widest integration in the platform: it covers the full commercial and financial cycle in both directions, so that the operational teams work in Skills Workflow and finance keeps working in VBS, with neither side retyping the other's data. The integration is modular — each flow can be switched on or off per company, so an agency can start with just clients and jobs and add the financial documents later. For the separate integration that sends **time** to VBS, see [VBS Timesheet](vbs-timesheet). --- ### Data Exchange Technology The integration calls the VBS API directly, using the address and the authentication headers configured by the agency. No files, no FTP servers and no locally installed application are required. It runs on a schedule, company by company, and only inside the working window the agency defines — each company chooses whether it runs on **Saturday** and **Sunday**, and between which **start** and **final** work hour. Outside that window the company is skipped, which keeps the load on VBS inside the hours the agency wants. --- ### Data Exchange (To Skills Workflow) | What is received | Notes | | --- | --- | | Clients | Created and updated as Billing Clients and Commercial Clients. Clients deactivated in VBS are moved to the stage set in **Commercial Client Cancel Stage**. Rappel clients can be excluded. | | Products | Imported on their own cadence, controlled by **Product Import Run Times**. They can be left inactive on arrival so somebody reviews them first. | | Projects | Optional. Imported with the nature and status configured for the company. | | Suppliers | Optional. Limited to the supplier type configured for the company. | | Users | Optional. New employees in VBS become Users and Employees in Skills Workflow, with the roles listed in **Default User Profile**. | **Employee fields received** When user import is enabled, the following are populated: Name, UserName, Company, Company Code, Department, Typology, E-mail, Phone, Hire Date, IsActive and SSO Username. The active status coming from VBS is written to the **User Active Status** field, so a person on leave can be told apart from an active one. Terminated employees are inactivated automatically. SSO Username is populated with the e-mail coming from VBS, and External ID is set from the e-mail on creation only. If **Department External Id** and **Typology External Id** are filled in, every imported employee is given that department and typology regardless of what the source says — useful when the agency does not want the VBS structure reproduced in Skills Workflow. --- ### Data Exchange (From Skills Workflow) | What is sent | Notes | | --- | --- | | Products | Optional, controlled by **Product Export** | | Projects | The name sent can be the project name only, or a composed name, depending on **Project Name Type** | | Jobs | Sent against the exported project | | Contracts | Can carry a cost centre | | Estimates | Can carry a cost centre | | Bills | Optional, controlled by **Bill Send**. Bills already exported can be re-sent when they change, if **Update Exported Bills** is enabled. A bill can be forwarded against its project contract or against its estimate. | | Client Credit Notes | Sent with the same rules as bills | | Supplier Invoices | Sent as purchase orders | Cost centres are optional and can be enabled independently for projects, jobs, contracts and estimates. --- ### Settings the Agency Controls The integration is configured per company, from the integration settings area in Skills Workflow. The settings fall into five groups: **Connection** — Api Link, Authorization Header, Id External System Header, System Code, User Login, Code, Id **Which flows are active** — Product Export, Project Import, Import Users, Import Suppliers, Bill Send **How records are built** — Project Name Type, Send Only Project Name, Project Nature, Project Status, Supplier Type, Default User Profile, Commercial Client Cancel Stage, Activate Product Manually, Exclude Rappel Clients, On Client Import Reload Product, On Project Apply Client Division **Cost centres and forwarding** — Send Project Cost Center, Send Job Cost Center, Send Contract Cost Center, Send Estimate Cost Center, Bill Project Contract Forward, Bill Estimate Forward, Update Exported Bills **When it runs** — Run On Saturday, Run On Sunday, Start Work Hour, Final Work Hour, Product Import Run Times Plus **Administrator Mail** and **Log Level Type**, which control notifications and logging. --- ### What the Agency Needs to Provide - The address of the VBS API, plus the authorization token, the external system identifier and the user the integration should operate as. - The company code and identifier in VBS. - A decision on which flows to enable, and the working window the integration should respect. - An administrator e-mail address to receive integration notifications. --- ### Monitoring and Error Handling Every run writes to the integration log inside Skills Workflow, at the level of detail chosen in **Log Level Type**. The log is cleared at the start of each run. A record that VBS rejects is logged with the reason VBS gave, and a summary e-mail is sent to the address configured in **Administrator Mail**. A failure on one record does not stop the run — the remaining records are still processed and everything that failed is reported at the end. --- ### Good to Know - Records are matched by their VBS identifier, stored on the Skills Workflow record. It should not be edited manually. - Because the flows are independent, switching one on later does not backfill history — it starts from the moment it is enabled. - Documents are exported once. **Update Exported Bills** is the exception: it deliberately re-sends bills that changed after export. --- ## VBS Timesheet URL: https://documentation.skillsworkflow.com/docs/integrations/vbs-timesheet Summary: This integration is separate from the VBS employee integration. ### Description This article describes the **VBS Timesheet** integration between `Skills Workflow` and **VBS**. This integration is separate from the [VBS](vbs) employee integration. While that one brings people into Skills Workflow, this one sends **time** back out: the hours and the leave that people record in Skills Workflow are pushed into VBS, so that the agency's cost, billing and payroll processes run on the same time data the teams actually entered. It takes care of the full life cycle of a time entry, not just the creation: - Time entries and leave created in Skills Workflow are sent to VBS. - Entries changed in Skills Workflow are updated in VBS. - Entries deleted in Skills Workflow are deleted in VBS. - The status VBS gives back to an entry is written onto the entry in Skills Workflow. --- ### Data Exchange Technology The integration calls the VBS timesheet API directly, using the address and the authentication headers configured by the agency. No files, no FTP servers and no locally installed application are required. The integration runs on a schedule, company by company, and only within the working window the agency defines. Each company can decide: - whether the integration runs on **Saturday** and on **Sunday** - the **start** and **final** work hour between which it is allowed to run Outside that window, the company is simply skipped. This keeps the traffic against VBS inside the hours the agency wants it to happen. Only time recorded from the configured **Timesheet Period From** date onwards is considered, so switching the integration on does not push years of historical time into VBS. --- ### Data Exchange (From Skills Workflow) **Time entries and leave** Time recorded in Skills Workflow is sent to VBS with the employee, the date, the duration, the client, the project and the work type. Leave is sent the same way, flagged as leave rather than as worked time. Public holidays registered in Skills Workflow are taken into account. Time can be sent either detailed or grouped, depending on how the agency wants VBS to see it: | Setting | Effect | | --- | --- | | Timesheet Group By Client | Entries are grouped by client before being sent | | Timesheet Group By Project | Entries are grouped by project before being sent | Once an entry is accepted, VBS returns its own identifier, which is stored on the entry in Skills Workflow. That identifier is what links the two records from then on. **Changes and deletions** When an entry that had already been sent is changed in Skills Workflow, the corresponding entry is updated in VBS. When it is deleted, it is deleted in VBS as well and the link between the two systems is cleared, so the time does not stay behind in VBS after being removed from Skills Workflow. --- ### Data Exchange (To Skills Workflow) After sending, the integration reads the entries back from VBS and updates the **status** of the corresponding timesheet or leave in Skills Workflow. This means the teams can see in Skills Workflow whether their time has been accepted downstream, without having to open VBS. --- ### Settings the Agency Controls The integration is configured per company, from the integration settings area in Skills Workflow: | Setting | What it does | | --- | --- | | Api Link | Address of the agency's VBS timesheet API | | Authorization Header | Authentication token sent with each request | | Id External System Header | Identifier of Skills Workflow as an external system in VBS | | User Login | User the integration operates as | | Code | Company code in VBS | | Timesheet Period From | Earliest date from which time is exported | | Timesheet Group By Client | Groups entries by client before sending | | Timesheet Group By Project | Groups entries by project before sending | | Run On Saturday / Run On Sunday | Whether the integration runs at the weekend | | Start Work Hour / Final Work Hour | Hours between which the integration is allowed to run | | Check Duplicity | Checks VBS for an existing entry before creating a new one, to avoid duplicates | | Administrator Mail | Address that receives the error notifications for this company | | Log Level Type | How much detail is written to the integration log | --- ### What the Agency Needs to Provide - The address of the VBS timesheet API, plus the authorization token, the external system identifier and the user the integration should operate as. - The company code in VBS. - The date from which time should start being exported. - The working window and grouping rules the agency wants applied. - An administrator e-mail address to receive integration notifications. --- ### Monitoring and Error Handling Every run writes to the integration log inside Skills Workflow, at the level of detail chosen in **Log Level Type**. The log is cleared at the start of each run. An entry that VBS rejects is recorded with the reason VBS gave, and a summary e-mail is sent to the address configured in **Administrator Mail**. Rejected entries do not stop the run — the remaining entries are still sent — and they are retried on the following run, so a transient problem in VBS resolves itself once the connection is back. --- ### Marketplace Export: Cost Centre Workspace A separate Marketplace component, **`VBS Time Sheet Cost Centre`** (Workspace, v3, Active — `[VBS] [Integrations] VBS Time Sheet Cost Centre v3 (Workspace) {Active} - Workspace.json`), implements a different mechanism from the settings-driven push described above: an in-app query view that produces a VBS-ready export row per timesheet entry, apparently for a manual/Excel-based hand-off rather than the automatic API push. Its own description (stored in the component, in Portuguese) frames it as "Business rules for the VBS Excel integration." - The query computes, per timesheet entry: the user's and client's external ids, the destination **Company** and **Division** codes, and a **CostCenter**, using lookup tables `LineofBusiness` and `DestinationCostCenter`. - Cost-center routing follows the discipline (department type) and the project's business line, with exceptions: divisions flagged "Don't Use Line of Business" (e.g. a central production division) and clients classified `InterCompany` instead use the user's own cost center and branch; if a project has no business line, the client's is used instead. - Freelancer-type users are excluded. - Only approved hours (`Aprovado = 'S'`) are included, and the row carries a fixed `cod_system = '24'` and `TypeHour = 'D'`. This looks like a client-specific customization layered on top of, or as an alternative to, the native VBS Timesheet integration described elsewhere on this page — not determinable from the export how the two relate operationally (e.g. whether this Workspace is used instead of the API push for this client, or as a manual reconciliation/audit view). --- ### Good to Know - Entries are matched by the VBS identifier stored on the Skills Workflow timesheet or leave. It should not be edited manually. - **Check Duplicity** is the safety net for cases where an entry may have reached VBS but the confirmation did not reach Skills Workflow. With it enabled, the integration checks VBS first instead of creating a second entry. - Projects need to carry their VBS reference for detailed (ungrouped) time to be exported against the right job. - Because the integration also reads statuses back, running it more often means the teams see the downstream status sooner. --- ## Visto URL: https://documentation.skillsworkflow.com/docs/integrations/Visto Summary: Visto is the external print-production system where artwork is sent for output, corrected and signed off. ### Description This article describes the integration between **Visto** and `Skills Workflow`. Visto is the external print-production system where artwork is sent for output, corrected and signed off. Skills Workflow is where the job it belongs to is managed. This integration keeps the job's stage honest. Once a piece has gone to production, the truth about where it stands lives in Visto — it is at output, it came back for adjustment, it was approved. Without the integration, that truth has to be relayed: someone in production tells someone in account management, who moves the job. Status in Skills Workflow becomes a lagging, second-hand account of what production already knows. With it, the job moves itself. Visto reports the change and Skills Workflow applies it, so the stage anyone looks at is the stage the piece is actually in. The two systems are linked the first time a job is matched: Visto's own reference is stored on the job, and from then on both sides are talking about the same piece. --- ### Data Exchange Technology Visto calls Skills Workflow directly over the web when a job's stage changes. The exchange is **event-driven** — there is no scheduled run, so the job moves within moments of the change in production. The outbound half of the connection — Skills Workflow telling Visto that a job is ready, or has moved — is delivered by the [Zappier](./zappier) package, which sends job and stage data to Visto through a Zapier webhook. --- ### Data Exchange (To Skills Workflow) **Stage changes → job stages** Visto sends the job number, its own reference for the piece, and the stage it has moved to. Skills Workflow finds the job, records Visto's reference if it does not have one yet, and moves the job to the matching stage. Nothing else about the job is overwritten — the integration moves the stage, it does not re-write the brief, the dates or the team. --- ### Data Exchange (From Skills Workflow) Handled by the [Zappier](./zappier) package. Jobs entering the production stages — *Enviado para Arizona*, *Em Ajuste Arizona*, *Aprovado Arizona* — are sent to Visto, with the fuller job detail sent the first time a job enters the flow and a lighter update on subsequent stage changes. --- ### What the Agency Needs to Provide - **Visto configured to call Skills Workflow** when a job's stage changes. - **Workflow stages on the job matching Visto's**, with valid transitions between them — see *Good to Know*. - **A notification e-mail address** to receive alerts when a stage cannot be applied. --- ### Monitoring and Error Handling If Visto reports a stage that the job has no valid transition to, the integration does not force it. It leaves the job where it is and sends an e-mail alert, so the workflow can be corrected rather than a job being pushed into a state its own process does not allow. --- ### Good to Know - **The workflow has to allow the move.** This is the usual reason a job appears stuck: Visto reported a stage, but no transition exists from where the job currently is. - **Jobs are matched by job number**, and Visto's reference is stored on the job the first time they are linked. - **Only the stage is updated** by the inbound flow — everything else about the job is left alone. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Visto-HandleWebhookRequest | Automation | 3 | Active | Inbound endpoint: applies a job stage update requested by Visto | | Visto-JobTransition-Get | Query | 3 | Active | Resolves the Skills Workflow transition matching Visto's requested stage, keyed by job number and Visto's stage code | | Visto-JobStageUpdate-Get | Query | 5 | Active | Builds the outbound payload (job, Visto stage label, comment, link) for a Skills Workflow stage change — not called by the exported automation | | Visto-jobToStage-Get | Query | 1 | Active | Alternate lookup of the transition to a named stage, keyed by stage name rather than Visto's external code — not called by the exported automation | Source: `[Visto] [Integrations] Visto-HandleWebhookRequest v3 (Automation) {Active}.json`, `[Visto] [Integrations] Visto-JobTransition-Get v3 (Query) {Active}.json`, `[Visto] [Integrations] Visto-JobStageUpdate-Get v5 (Query) {Active}.json`, `[Visto] [Integrations] Visto-jobToStage-Get v1 (Query) {Active}.json`. #### How It Works **Inbound (Visto → Skills Workflow, exported):** 1. Visto calls the automation's HTTP endpoint with a body containing `Action`, `ID_Skills` (the Skills Workflow job number), `ID_VG` (Visto's own job id) and `Etapa` (Visto's stage code). 2. If `Action` is `Update`, `Visto-JobTransition-Get` looks up the job by `ID_Skills` and finds the transition whose external id matches `Etapa`. It also reports whether the job already has an `ExternalId` set (`Exists`) or not (`Create`). 3. If no matching transition is found, an email alert is sent ("... - Transition Not Available") to `ines@skillsworkflow.com` and `helder.barreiros@skillsworkflow.com`. 4. If the job doesn't yet have an `ExternalId`, it's set to `ID_VG` (`PATCH /api/jobs/{jobId}`). 5. The transition is applied (`POST /api/v3/posts`, `Actions.transition`). **Outbound (Skills Workflow → Visto):** `Visto-JobStageUpdate-Get` is built to run when a deliverable enters one of three stages — "Enviado para Arizona", "Em Ajuste Arizona", "Aprovado Arizona" (naming suggests an Arizona-brand large-format printer output stage) — and maps each to a Visto-facing label (`To do`, `Para ajustar`, `Aprovado`), together with the latest comment and a link back to the job. **This direction is actually implemented by the [Zappier](./zappier) Marketplace package** — despite its name, that package's components are internally named `Visto-StageChanged` / `Visto-JobStageUpdate-Get` / `Visto-JobById-Get` and send exactly this data to Visto via a Zapier webhook. See that page for the full flow. #### External System Contact Points - Inbound: Visto calls this automation's own HTTP endpoint (URL not included) with the job update payload. - Outbound: via the [Zappier](./zappier) package — `POST https://hooks.zapier.com/hooks/catch/16059441/29959bj/`. - Skills Workflow's own API: `PATCH /api/jobs/{jobId}`, `POST /api/v3/posts`, named query `Visto-JobTransition-Get`. #### Configuration - Not determinable from the export — no configuration key or system parameter is referenced by the inbound automation. #### Open Questions - `Visto-jobToStage-Get` is not called by any exported automation, in either this package or [Zappier](./zappier) — whether it's dead, used by an unexported component, or a manual/ad-hoc query is not determinable. - The copies of `Visto-JobStageUpdate-Get` and `Visto-JobTransition-Get` exported under [Zappier](./zappier) are older versions (v2) than the ones here (v5, v3) — whether that package is running stale copies isn't determinable. --- ## WK Radar URL: https://documentation.skillsworkflow.com/docs/integrations/WK-Radar Summary: WK Radar is the agency's ERP — where the client and supplier ledgers live and where sales and purchase orders are processed. ### Description This article describes the integration between **WK Radar** and `Skills Workflow`. WK Radar is the agency's ERP — where the client and supplier ledgers live and where sales and purchase orders are processed. Skills Workflow is where the work is run and the documents originate. The integration keeps the two aligned so that the commercial teams work in Skills Workflow and finance keeps working in WK Radar, without either side maintaining the other's lists. It takes care of two jobs: - **Bringing the master data in** — active clients, suppliers and services registered in WK Radar are created and kept up to date in Skills Workflow every day, so documents are raised against records finance recognises. - **Sending the documents out** — bills and supplier invoices are registered in WK Radar as sales and purchase orders, and the reference WK Radar assigns is written back onto the document. --- ### Data Exchange Technology The exchange runs over the WK Radar web API. Skills Workflow authenticates for a token and then calls WK Radar directly. No files and no locally installed application are required. The master data is refreshed on a **daily schedule**, which pulls suppliers, clients and services in sequence. To avoid missing late edits, each run looks back further than a single day rather than only at the previous 24 hours. Documents are sent **as they are approved**, not on a schedule. --- ### Data Exchange (To Skills Workflow) | Received from WK Radar | Becomes in Skills Workflow | | --- | --- | | Active clients | Billing clients | | Active suppliers | Suppliers | | Services | Services | Only records marked active in WK Radar are imported, so retired clients and suppliers do not reappear. --- ### Data Exchange (From Skills Workflow) | Document | Sent to WK Radar as | | --- | --- | | **Bill** | Sales order (*pedido*) | | **Supplier Invoice** | Purchase order (*ordem de compra*) | The reference WK Radar returns is stored on the Skills Workflow document. The bill flow is fully built, but the trigger that fires it is switched off in this configuration, so approved bills do not currently reach WK Radar on their own. The supplier invoice flow and the daily master-data refresh are unaffected. --- ### What the Agency Needs to Provide - **A WK Radar account with API access**, plus the address and credentials for Skills Workflow. - **The stages** on the Bill and Supplier Invoice document types that mean "approved and ready to register". - **Client and supplier records carrying their WK Radar identifiers**, so documents resolve to the right ledger entries. --- ### Good to Know - **The daily refresh looks back more than one day**, so a record edited in WK Radar after that day's run has already completed is still picked up. - **Only active records are imported** — inactive clients and suppliers in WK Radar are left out by design. - **Documents are matched by their WK Radar reference**, stored on the Skills Workflow document after a successful registration. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | WKRadar-ScheduledUpdate | Automation | 2 | Active | Daily: enqueues the Suppliers/Clients/Services refreshes | | WKRadar-Authenticate | Automation | 2 | Active | Shared helper: gets a WK Radar API token | | WKRadar-Clients | Automation | 2 | Active | Pulls active clients changed since a given date from WK Radar | | WKRadar-Suppliers | Automation | 2 | Active | Pulls active suppliers changed since a given date | | WKRadar-Services | Automation | 2 | Active | Pulls services from WK Radar | | WKRadar-IntegrateBill | Automation | 2 | Active | Sends a bill to WK Radar as a sales order ("Pedido") | | WKRadar-BillStageChanged | Webhook | 1 | **Disabled** (`active: false`) | Would fire `WKRadar-IntegrateBill` on a Bill reaching "Integrated" — currently off, and its URL points at a `playground-dev` tenant | | WKRadar-IntegrateSupplierInvoice | Automation | 1 | Active | Sends a supplier invoice to WK Radar as a purchase order | | WKRadar-GetClient | Query | 2 | Active | Resolves an existing client for the Clients sync | | WKRadar-GetSupplier | Query | 2 | Active | Resolves an existing supplier for the Suppliers sync | | WKRadar-GetService | Query | 2 | Active | Resolves an existing service for the Services sync | | WKRadar-GetBillById | Query | 3 | Active | Builds the outbound payload for a bill | | WKRadar-GetSupplierInvoiceById | Query | 1 | Active | Builds the outbound payload for a supplier invoice | Source: `[WK Radar] [Integrations] WKRadar-ScheduledUpdate v2 (Automation) {Active}.json`, `[WK Radar] [Integrations] WKRadar-Authenticate v2 (Automation) {Active}.json`, `[WK Radar] [Integrations] WKRadar-Clients v2 (Automation) {Active}.json`, `[WK Radar] [Integrations] WKRadar-Suppliers v2 (Automation) {Active}.json`, `[WK Radar] [Integrations] WKRadar-Services v2 (Automation) {Active}.json`, `[WK Radar] [Integrations] WKRadar-IntegrateBill v2 (Automation) {Active}.json`, `[WK Radar] [Integrations] WKRadar-BillStageChanged v1 (Webhook) {Active}.json`, `[WK Radar] [Integrations] WKRadar-IntegrateSupplierInvoice v1 (Automation) {Active}.json`, and the named queries above. #### How It Works 1. `WKRadar-ScheduledUpdate` runs daily, computes a date 10 days before yesterday, and enqueues `WKRadar-Suppliers`, `WKRadar-Clients` and `WKRadar-Services` as background work with that date. 2. Each pull authenticates via `WKRadar-Authenticate` (`POST {host}/wk.api/api/v1/token`), calls the matching WK Radar endpoint (`GET /wk.api/api/empresarial/v1/cliente|fornecedor|servico`, filtered by change date and `Situacao=Ativo` for clients/suppliers), resolves each record against Skills Workflow (`WKRadar-GetClient` / `WKRadar-GetSupplier` / `WKRadar-GetService`), and creates or updates it. 3. `WKRadar-IntegrateBill` runs `WKRadar-GetBillById`, then `POST {host}/RadarWebWebServices/Areas/comercial/Comercial.svc/json/GravarPedido` to record the sales order, and patches the bill (`PATCH /api/bills/{id}`) with the result. It's designed to be webhook-triggered (its body shape expects `event.documentId.id`), but the only matching webhook in the export, `WKRadar-BillStageChanged`, is disabled. 4. `WKRadar-IntegrateSupplierInvoice` follows the same pattern for purchase orders (`WKRadar-GetSupplierInvoiceById`, `POST {host}/api/compras/v1/ordem-compra`, `PATCH /api/supplier-invoices/{id}`) — no webhook for it is included in this export at all. #### External System Contact Points - WK Radar API (`{host}` from a `Config` configuration key): `POST /wk.api/api/v1/token`, `GET /wk.api/api/empresarial/v1/cliente`, `.../fornecedor`, `.../servico`, `POST /RadarWebWebServices/.../GravarPedido`, `POST /api/compras/v1/ordem-compra`. - Skills Workflow's own API/analytics: the named queries above; `POST /api/v3/billing-clients`, `POST /api/v3/suppliers`, `POST /api/v3/services`, `PATCH /api/bills/{id}`, `PATCH /api/supplier-invoices/{id}`. #### Configuration - A `Config` configuration key — holds the WK Radar host and credentials. Values are not part of the export. #### Open Questions - `WKRadar-BillStageChanged` is disabled and points at a `playground-dev` tenant URL — whether bill integration is meant to be re-enabled with a production webhook, or was replaced by something else, isn't determinable from the export. - No webhook for `WKRadar-IntegrateSupplierInvoice` is included in this export — what currently triggers it, if anything, is not determinable. --- ## WMS URL: https://documentation.skillsworkflow.com/docs/integrations/WMS Summary: WMS is a separate Work Management System that runs alongside Skills Workflow, each holding the same work for a different audience. "WMS" ships as two Marketplace packages, `WMS (Server)` and `WMS (Client)`, sharing the same authentication secret and the same `/api/integration-workflows/{id}/execute` call pattern used by the [Client and Agencies](./client-and-agencies) tenant bridge elsewhere in this export. This strongly suggests **WMS is another Skills Workflow tenant** acting as the agency's Work Management System, rather than a third-party product — though no file states this explicitly. Both halves are documented together on this page: **Server** receives events from WMS and creates/updates records here; **Client** sends this tenant's own events to WMS. ### Description This article describes the **WMS** integration in `Skills Workflow`. WMS is a separate Work Management System that runs alongside Skills Workflow, each holding the same work for a different audience. This integration keeps the two continuously mirrored, in both directions, so a job exists once as far as the people using it are concerned — regardless of which system they happen to be in. This is the most complete two-way sync in this section. Rather than exchanging one document type on approval, it mirrors the working record itself and everything attached to it: the project, the job, the brief, the comments, who is assigned, and the client's products. When any of those changes on one side, the other follows. The value is that neither population has to move. Teams working in WMS keep working there; teams working in Skills Workflow keep working here; and neither is looking at a stale copy or waiting on someone to relay a status. The two systems behave as one shared record with two front doors. --- ### Data Exchange Technology The two systems call each other directly over the web. Every request in either direction carries a shared secret that the receiving side checks before accepting anything, and a request that fails that check is rejected outright. The exchange is **event-driven in both directions** — it runs when something changes, not on a schedule, so the two sides stay in step continuously rather than converging at the end of a run. Incoming changes are **queued and processed in the background** rather than applied inline, so a burst of activity on one side does not slow down the other, and each change carries a retry count so it can be re-attempted rather than lost. --- ### What Is Exchanged Both directions cover the same ground: | Record | Created | Updated | Stage change | Deleted | | --- | --- | --- | --- | --- | | **Project** | ✓ | ✓ | ✓ | | | **Job** | ✓ | ✓ | ✓ | | | **Brief** | ✓ | | | | | **Comment** | ✓ | ✓ | | | | **Assignment** (who is on the job) | ✓ | | | ✓ | | **Client product** | | ✓ | | | When a job arrives that belongs to a project the receiving side does not have yet, the **project is created first**, then the job underneath it, then the team assigned — so work never lands orphaned. --- ### What the Agency Needs to Provide - **Both systems' addresses**, and a shared secret agreed between them. - **Matching workflow stages** on both sides, so a stage change on one can be applied on the other. - **Agreement on scope** — which departments and record types should cross over. Some events are deliberately filtered; see *Good to Know*. --- ### Good to Know - **Not everything crosses over.** Job updates, for instance, can be scoped to a specific department, so only the work that matters to the other system is mirrored. - **Project stage changes are conditional** — a project only reports its stage change if it actually has jobs underneath it, which prevents empty projects generating noise. - **A rejected request is silent by design.** A request whose shared secret does not match is refused without side effects, so a misconfigured connection fails closed rather than writing bad data. - Because the sync is two-way and event-driven, a change made on either side is expected to appear on the other within moments — a persistent one-way gap points at the connection rather than at timing. --- ### Technical Reference #### Components **Server side** (receives from WMS — `[WMS (Server)] [Integrations] Wms-...`): | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Wms-ProcessWebhookTask | Automation | 17 | Active | Single inbound endpoint: validates the shared secret and enqueues `Wms-ExecuteWebhookTask` | | Wms-ExecuteWebhookTask | Automation | 18 | Active | Dispatches by event type + document type to the automation below that handles it | | Wms-CreateJobAndProject | Automation | 18 | Active | Creates a job (and its project, if new) from an incoming Deliverable-created event | | Wms-UpdateJob | Automation | 19 | Active | Updates a job (and patches its project) from an incoming Deliverable-updated event | | Wms-MoveStage | Automation | 17 | Active | Moves a job's stage from an incoming Deliverable stage-updated event | | Wms-MoveProjectStage | Automation | 1 | Active | Moves a project's stage from an incoming Project stage-updated event | | Wms-CreateDocumentBrief | Automation | 17 | Active | Creates a brief from an incoming DocumentBrief-created event | | Wms-CreateOrUpdatePost | Automation | 17 | Active | Creates or updates a comment from an incoming Post event | | Wms-CreateOrDeleteAssignment | Automation | 17 | Active | Creates or removes a team assignment from an incoming Assignment event | | Wms-UpdateProject | Automation | 17 | Active | Updates a project from an incoming Project-updated event | | Wms-UpdateProduct | Automation | 17 | Active | Updates a commercial product from an incoming CommercialClientProduct-updated event | | Wms-TestQuery | Automation | 17 | Active | Diagnostic: runs `wms-automation_ProjectLookup` — not part of the production flow | | 12 supporting `wms-automation_*` named queries | Query | various | Active | Look up / validate the records each automation above acts on | **Client side** (sends to WMS — `[WMS (Client)] [Integrations] Wms...`): | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Wms - On Job Created | Automation | 18 | Active | Sends a new job (with its briefs and assignments) to WMS | | Wms - On Job Updated | Automation | 17 | Active | Sends a job update to WMS | | Wms - On Stage Changed | Automation | 18 | Active | Sends a job stage change to WMS | | Wms - On Project Updated | Automation | 17 | Active | Sends a project update to WMS | | Wms - On Project Stage Changed | Automation | 2 | Active | Sends a project stage change to WMS, if the project has valid jobs | | Wms - On DocumentBrief Created | Automation | 17 | Active | Sends a new brief to WMS | | Wms - On Post Created | Automation | 17 | Active | Sends a new comment to WMS | | Wms - On Assignment Created Or Deleted | Automation | 17 | Active | Sends a team assignment/unassignment to WMS | | Wms - On Product Updated | Automation | 17 | Active | Sends a commercial product update to WMS | | Wms-CreateDocumentBriefEvent | Webhook | 17 | Active | Fires on DocumentBrief creation | | Wms-CreatePostEvent | Webhook | 17 | Active | Fires on Post creation | | Wms-CreatedAssignmentEvent / Wms-DeleteAssignmentEvent | Webhook | 17 | Active | Fire on Assignment creation / deletion | | Wms-OnJobStageChange | Webhook | 17 | Active | Fires on Deliverable `StageUpdated` | | Wms-OnProjectStageChange | Webhook | 1 | Active | Fires on Project `StageUpdated` | | Wms-UpdateJobEvent | Webhook | 17 | Active | Fires on Deliverable `Updated`, filtered to one specific department | | Wms-UpdateProjectEvent | Webhook | 17 | Active | Fires on Project `Updated` | | Wms-UpdatedCommercialClientProduct | Webhook | 17 | Active | Fires on CommercialClientProduct `Updated` | | 12 supporting `wms-automation*` named queries | Query | various | Active | Build the payload each automation sends to WMS | Source: files under `[WMS (Server)] [Integrations] Wms-...` / `wms-automation_...` (27 files, 26 distinct components) and `[WMS (Client)] [Integrations] Wms...` / `wms-automation...` (30 files, 30 distinct components) in the Marketplace export. #### How It Works **Receiving from WMS (Server side):** 1. WMS calls `Wms-ProcessWebhookTask`'s endpoint. It checks the request header `x-shared-secret` against a hardcoded value; a mismatch or empty body exits without processing. It then adds a `retryCount` of `0` if missing, and enqueues `Wms-ExecuteWebhookTask` (confirmed by matching automation id `1ab7d093-249b-41bf-a099-443c98b5663c`) as background work with the payload Base64-encoded. 2. `Wms-ExecuteWebhookTask` decodes the payload and dispatches on `Payload.type` (`Created` / `Updated` / `StageUpdated` / `Deleted`) crossed with `Payload.documentType`: - `Created` + `Deliverable` → `Wms-CreateJobAndProject`; `+ DocumentBrief` → `Wms-CreateDocumentBrief`; `+ Post` → `Wms-CreateOrUpdatePost`; `+ Assignment` → `Wms-CreateOrDeleteAssignment`. - `Updated` + `Deliverable` → `Wms-UpdateJob`; `+ Project` → `Wms-UpdateProject`; `+ Post` → `Wms-CreateOrUpdatePost`; `+ CommercialClientProduct` → `Wms-UpdateProduct`. - `StageUpdated` + `Deliverable` → `Wms-MoveStage`; `+ Project` → `Wms-MoveProjectStage`. - `Deleted` + `Assignment` → `Wms-CreateOrDeleteAssignment`. 3. Each target automation runs its own lookup query (e.g. `wms-automation_jobDataLookup`, `wms-automation_ProjectDataLookup`, `wms-automation_AssignmentDataLookup`) and applies the change via Skills Workflow's own API (`POST /api/jobs`, `POST /api/v3/projects`, `POST /api/documentBriefs`, `POST /api/posts`, `PATCH /api/jobs/{id}`, `PATCH /api/projects/{id}`, `PATCH /api/commercialproducts/{id}`). 4. `Wms-CreateJobAndProject` additionally creates the project first if `wms-automation_ProjectLookup` finds none, then transitions both the new project and job to their first available stage. **Sending to WMS (Client side):** 1. Each of the 9 "Wms - On ..." automations is fired by its matching webhook, runs a lookup query to validate and build the payload (e.g. `wms-automation_jobLookupById`, `wms-automation_ProjectLookupById`, `wms-automation_AssignmentById`), and `POST`s the result to `{host}/api/integration-workflows/{automationId}/execute` — landing on the Server side's `Wms-ProcessWebhookTask`. The destination host and target automation id are read from a `Parameters` (or, for Project Stage Changed, `Config`) configuration key, not hardcoded, so which WMS environment/tenant receives each event type is configurable per automation. 2. A few send extra context beyond the bare record: `Wms - On Job Created` also fetches the job's and project's briefs (`GET /api/documentBriefs?...`) and the project's team assignments (`wms-automation_ProjectAssignmentsById`); `Wms - On Assignment Created Or Deleted` first checks the job and project are still valid (`wms-automation_jobIsValidById`, `wms-automation_ProjectIsValidById`); `Wms - On Project Stage Changed` only sends if the project has valid jobs under it (`wms-automation-ProjectHasValidJobs`). 3. `Wms-UpdateJobEvent` is filtered at the webhook level to a single department (id `284db428-3d20-4a2b-81d6-35033e0caaa2`) — job updates outside that department don't reach WMS. #### External System Contact Points - Client → WMS: `POST {host}/api/integration-workflows/{automationId}/execute`, header `x-shared-secret`. Host and automation id are per-automation configuration values, not fixed. - WMS → Server: inbound calls to `Wms-ProcessWebhookTask`'s own HTTP endpoint (URL not included), authenticated with the same header. - Skills Workflow's own API/analytics on each side: the `wms-automation*` named queries; `POST /api/jobs`, `POST /api/v3/projects`, `POST /api/documentBriefs`, `POST /api/posts`, `PATCH /api/jobs/{id}`, `PATCH /api/projects/{id}`, `PATCH /api/commercialproducts/{id}`, `PUT /api/v3/documentUserFieldValues`, `PUT /api/v3/post-comments/{id}`, `GET /api/documentBriefs`. #### Configuration - Server side: the shared secret validated by `Wms-ProcessWebhookTask` is hardcoded in the automation rather than a configuration key. - Client side: configuration key **`Parameters`** (and, inconsistently, `Config` on `Wms - On Project Stage Changed`) — holds `host` and `automationId` per automation. - Values are not part of the export. All 9 Client-side webhooks carry the same hardcoded shared `secret` value in their own JSON, matching the value `Wms-ProcessWebhookTask` checks on the Server side. The value is not reproduced here. If this export is genuine, treat it as compromised and rotate it — since both sides use the same secret, rotating it requires updating both. #### Open Questions - Whether "WMS" is genuinely another Skills Workflow tenant (as the URL pattern and shared-secret mechanism suggest) or a third-party product built to the same API shape is not stated anywhere in the export. - `Wms-TestQuery` looks like a leftover diagnostic automation rather than part of the production dispatch table. - Why `Wms - On Project Stage Changed` reads a `Config` configuration key while every other Client-side automation reads `Parameters` is not explained — possibly a naming inconsistency introduced when it was added later (its version, v2, is much lower than its siblings' v17/v18). - Why `Wms-UpdateJobEvent` is scoped to a single department while the other Deliverable events aren't is not explained in the export. --- ## Workday Informatica URL: https://documentation.skillsworkflow.com/docs/integrations/Workday-Informatica Summary: Workday is the HR system of record — where employees request time off and where it is approved. ### Description This article describes the integration between **Workday** and `Skills Workflow`. Workday is the HR system of record — where employees request time off and where it is approved. Skills Workflow is where the consequences of that time off are felt: resourcing, scheduling, capacity, FTE and timesheets all depend on knowing who is actually available. This integration brings absence out of HR and into planning. If leave only lives in Workday, every resourcing view in Skills Workflow is quietly wrong — someone is shown as available on a week they are on holiday, and the plan is built on it. Here, approved time off appears against the person automatically, and disappears again if it is cancelled. It covers both shapes of absence: - **Individual absences** — single days and short periods. - **Leave periods** — longer, structured blocks of time off. --- ### Data Exchange Technology The exchange runs through an **Informatica integration layer in front of Workday**, rather than calling Workday directly. Skills Workflow authenticates against that layer and requests the absence data published for it. Both syncs are **scheduled**: | Sync | Runs | | --- | --- | | Absences | Once a day | | Leave periods | Every 6 hours | The exchange is **one-way**: Workday is the source of truth, and Skills Workflow follows it. The integration is scoped to a defined set of companies, so only the entities that belong in it are processed. --- ### Data Exchange (To Skills Workflow) **Absences and leave periods → Leave** Each absence record is checked against Skills Workflow before anything is applied, and then one of the following happens: | Situation | Result | | --- | --- | | The absence is new | Leave is created against the employee, recorded as though entered by them | | The absence was cancelled in Workday | The corresponding leave is removed | | The absence already exists unchanged | Nothing — it is skipped rather than re-created | | The employee is not in scope | Skipped | Because cancellations are handled as well as approvals, a holiday that is later withdrawn in Workday stops blocking the calendar in Skills Workflow, instead of remaining as a phantom absence. --- ### What the Agency Needs to Provide - **Access to the Workday integration endpoints** published through Informatica, plus the credentials for Skills Workflow. - **Employees present in Skills Workflow** and matched to their Workday record. - **Leave types in Skills Workflow** corresponding to the absence types Workday sends. - **The companies in scope** for the integration. --- ### Monitoring and Error Handling The integration does not guess when a record cannot be placed. An absence is reported rather than applied when the employee cannot be matched, the leave type does not exist in Skills Workflow, the leave year cannot be resolved, or a cancellation refers to leave that is not there. In each case two things happen: an **e-mail notification** is sent, and the attempt is **recorded in the company's integration log**, so there is a durable record to review rather than only a message in someone's inbox. A problem with one record does not stop the run. --- ### Good to Know - **Workday is the source of truth for absence.** Leave entered by hand in Skills Workflow for a synced employee will be overwritten or removed by the next run. - **Leave types have to exist first.** A new absence type introduced in Workday needs a matching leave type in Skills Workflow before it can be imported. - **Absence is recorded against the employee**, so it appears in resourcing and scheduling as though they entered it themselves. - The two syncs run at different frequencies, so a long leave period may appear on a different cadence to a single day's absence. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Workday - Absence | Automation | 3 | Active | Daily sync of single-day absences from Workday into Skills Workflow leaves | | Workday - CCW | Automation | 2 | Active | 6-hourly sync of Workday leave periods into Skills Workflow leave periods | | Workday-Absence-Validate-Get | Query | 3 | Active | Validates a Workday absence record and decides create/delete/error | | Workday-CCWAbsence-Validate-Get | Query | 3 | Active | Same validation for leave-period (CCW) records | | Workday-Companies-Get | Query | 2 | Active | Lists the companies (`VML%`, excluding some) this integration applies to | Source: `[Workday Informatica] [Integrations] Workday - Absence v3 (Automation) {Active}.json`, `[Workday Informatica] [Integrations] Workday - CCW v2 (Automation) {Active}.json`, `[Workday Informatica] [Integrations] Workday-Absence-Validate-Get v3 (Query) {Active}.json`, `[Workday Informatica] [Integrations] Workday-CCWAbsence-Validate-Get v3 (Query) {Active}.json`, `[Workday Informatica] [Integrations] Workday-Companies-Get v2 (Query) {Active}.json`. #### How It Works Both automations follow the same shape, calling Workday's Informatica-hosted integration endpoints: 1. Authenticate: `POST {AuthUrl}` with Basic auth (credentials from the `workday-informatica` configuration key), expecting a bearer `access_token` back. A non-200 response exits with "Authentication Failure". 2. Pull data: - **Absence**: `POST {BaseUrl}/Workday_Absence_VML_LATAM_SubscriptionProcess100/v1/Workday_Absence_VML_LATAM_SubscriptionProcess`. - **CCW**: the equivalent `Workday_Ccw_VML_LATAM_SubscriptionProcess100` endpoint. Both normalize the response (a single object or an array) into a list and loop over each record. 3. For each record, a named query (`Workday-Absence-Validate-Get` / `Workday-CCWAbsence-Validate-Get`) checks the employee, vacation type and year against Skills Workflow and returns an `action`: - `Create` → the absence/leave period is created (`POST /api/leaves` for Absence; `POST /api/v3/leave-periods` then `PUT /api/leaves/status` / `PUT /api/v3/leave-periods/{id}` for CCW), impersonating the employee via `X-AppUser`. - `delete` → the existing leave is removed (`DELETE /api/leaves?forceDelete=true`). - `user` / `create-exists` → silently skipped (already up to date, or the user isn't applicable). - `vacationType`, `year`, `delete-missing` → treated as errors: an HTML email is sent to `helder@skillsworkflow.com` and `skills.workflow@vml.com`, and the attempt is recorded via `POST /api/v3/company-integration-logs` (documentType `Leave`, `documentName: WorkdayLeave`). 4. A create/update call that itself fails (non-200) also emails the same error notification before logging. #`Workday-Companies-Get` restricts the integration to companies whose name matches `VML%` (with some exclusions in its `WHERE` clause) — this is a **VML**-specific integration. #### External System Contact Points - Workday (via an Informatica-hosted integration layer): `POST {AuthUrl}` (Basic auth), `POST {BaseUrl}/Workday_Absence_VML_LATAM_SubscriptionProcess100/v1/...` and `.../Workday_Ccw_VML_LATAM_SubscriptionProcess100/v1/...` (Bearer auth). - Skills Workflow's own API: `POST /api/leaves`, `DELETE /api/leaves`, `POST /api/v3/leave-periods`, `PUT /api/leaves/status`, `PUT /api/v3/leave-periods/{id}`, `POST /api/v3/company-integration-logs`, named queries `Workday-Absence-Validate-Get`, `Workday-CCWAbsence-Validate-Get`, `Workday-Companies-Get`. #### Configuration - Configuration key **`workday-informatica`** — holds `AuthUrl`, `AuthorizationHeader` (Basic auth credentials) and `BaseUrl`. Values are not part of the export. - Scheduler: Absence runs daily; CCW runs every 6 hours. - Error/notification recipients are hard-coded in the automation bodies (`helder@skillsworkflow.com`, `skills.workflow@vml.com`) rather than configured. #### Open Questions - "CCW" is not spelled out anywhere in the export — its exact meaning (a Workday leave-period category) is not determinable. - The precise validation rules inside `Workday-Absence-Validate-Get` / `Workday-CCWAbsence-Validate-Get` (how `vacationType`, `year` and `delete-missing` errors are triggered) depend on their full SQL, which joins several internal vacation/typology tables not fully explored here. --- ## Zappier URL: https://documentation.skillsworkflow.com/docs/integrations/Zappier Summary: Visto is the external print-production system. Despite the Marketplace package being named "Zappier" (and its files prefixed `Zappier-`), every component's own internal name, category (`Visto-Integration`) and behavior show this is the **outbound** side of the [Visto](./visto) print-production integration — notifying Visto of job creation and stage changes via a Zapier webhook, rather than calling Visto directly. See [Visto](./visto) for the inbound side (Visto telling Skills Workflow about stage changes). ### Description This article describes the outbound half of the [Visto](./visto) integration, delivered through **Zapier**. [Visto](./visto) is the external print-production system. That page covers the inbound direction — production telling Skills Workflow that a piece has moved. This package covers the opposite direction: Skills Workflow telling Visto that a job is ready to be produced, and keeping it informed as the job advances. The two together close the loop. A job reaches the stage where it should go to production, and production learns about it without anyone sending it over. From then on, each side reports its own changes to the other. Zapier sits in the middle as the delivery mechanism. Rather than Skills Workflow integrating against Visto directly, it posts the job to a Zapier webhook, and Zapier routes it onward. The practical benefit is that the routing can be changed — a new destination, an extra notification, a transformation — without altering anything in Skills Workflow. --- ### Data Exchange Technology The exchange is a **single outbound call to a Zapier webhook**, made when a job's stage changes. There is no schedule; the call happens on the stage change itself. The webhook address is the credential — anyone holding it can post to it — so it is treated as a secret. --- ### Data Exchange (From Skills Workflow) **Job stage changes → Visto** The integration reacts to jobs entering the production stages, and sends a different amount of detail depending on whether Visto is meeting the job for the first time: | Situation | What is sent | | --- | --- | | A job enters production for the first time (*Enviado para Arizona*, from a stage other than *Devolvido Arizona*) | The full job detail — enough for Visto to create its own record | | A job re-enters production after being returned (*Enviado para Arizona*, from *Devolvido Arizona*) | A stage update | | A job moves to *Em Ajuste Arizona*, *Em aprovação Arizona* or *Aprovado Arizona* | A stage update | | Any other stage change | Nothing is sent | Sending the fuller record only on first entry keeps the ongoing traffic light while still giving Visto everything it needs up front. --- ### What the Agency Needs to Provide - **A Zapier account** with a catch-hook configured to receive the job data and route it to Visto. - **The production stages** above on the job document type, named so they can be matched. - **The webhook address**, configured in Skills Workflow and treated as a secret. --- ### Good to Know - **Only the production stages trigger it.** Movement elsewhere in the job's workflow sends nothing. - **The first entry into production sends more than later ones** — this is deliberate, not an inconsistency. - **Zapier is a relay, not the destination.** What ultimately happens to the job data depends on how the Zap is configured, which is managed in Zapier rather than in Skills Workflow. - Despite this package being named "Zappier" in the Marketplace, everything in it belongs to the Visto integration — see the [Visto](./visto) page for the other direction. --- ### Technical Reference #### Components | Name | Type | Version | Stage | Role | | --- | --- | --- | --- | --- | | Visto-StageChanged (package name `Zappier-CreateJob`) | Automation | 3 | Active | Builds the job payload and sends it to a Zapier webhook | | Visto-StageChanged (package name `Zappier-OnJobStageUpdated`) | Webhook | 3 | Active | Fires the automation on Deliverable stage changes | | Visto-JobById-Get (package name `Zappier-GetJobById`) | Query | 5 | Active | Builds the full job payload, used the first time a job enters the flow | | Visto-JobStageUpdate-Get | Query | 2 | Active | Builds a lighter stage-update payload, used for subsequent stage changes | | Visto-JobTransition-Get | Query | 2 | Active | Present in this package but not called by the exported automation | Source: `[Zappier] [Integrations] Zappier-CreateJob v3 (Automation) {Active}.json`, `[Zappier] [Integrations] Zappier-OnJobStageUpdated v3 (Webhook) {Active}.json`, `[Zappier] [Integrations] Zappier-GetJobById v5 (Query) {Active}.json`, `[Zappier] [Integrations] Visto-JobStageUpdate-Get v2 (Query) {Active}.json`, `[Zappier] [Integrations] Visto-JobTransition-Get v2 (Query) {Active}.json`. #### How It Works 1. The webhook fires on `StageUpdated` for a `Deliverable` where the destination stage is "Enviado para Arizona", "Em Ajuste Arizona" or "Aprovado Arizona" (matching automation id `98610c89-b3a6-455b-9ecd-e7b2dbe922b4`). 2. The automation branches on the **destination** stage: - "Enviado para Arizona" **and** the job came **from** "Devolvido Arizona" → treated as a stage update (`Visto-JobStageUpdate-Get`). - "Enviado para Arizona" from any other stage → treated as a new job entering the flow (`Visto-JobById-Get`, the fuller payload). - "Em Ajuste Arizona", "Em aprovação Arizona" or "Aprovado Arizona" → always a stage update (`Visto-JobStageUpdate-Get`). 3. Either way, the resulting payload is `POST`ed as JSON to a Zapier "catch hook" URL (`https://hooks.zapier.com/hooks/catch/16059441/29959bj/`) — Zapier then presumably relays it into Visto, though what Zapier does with it isn't part of this export. This lines up with the `Visto-JobStageUpdate-Get` query documented on the [Visto](./visto) page as "referenced but not exported" — it's exported here, under this differently-named package, and resolves that page's open question about what sends stage updates to Visto. #### External System Contact Points - Zapier: `POST https://hooks.zapier.com/hooks/catch/16059441/29959bj/` — no authentication beyond the URL itself being a secret. - Skills Workflow's own analytics: named queries `Visto-JobById-Get`, `Visto-JobStageUpdate-Get`. #### Configuration - The Zapier catch-hook URL is hardcoded in the automation rather than configured via a configuration key. #### Open Questions - What the Zapier "Zap" behind that catch-hook URL actually does with the payload (forward to Visto, transform it, etc.) is entirely outside this export. - The query versions here (`Visto-JobStageUpdate-Get` v2, `Visto-JobTransition-Get` v2) are older than the versions exported under the `Visto` module (v5, v3) with the same names — whether this package is running stale copies or the two are meant to diverge is not determinable. --- ## ZiFlow URL: https://documentation.skillsworkflow.com/docs/integrations/ziflow Summary: ZiFlow is the online proofing tool where creative work is reviewed and approved. This page described only the inbound "proof decision moves the job's stage" webhook. The exported package (Module `Ziflow`, 21 components after de-duplicating repeated attachments) is considerably larger: it also includes a full **Create/Edit Proof workspace** embedded on the Job record, a **My Pending Proofs** / **Proofing** panel for reviewing proofs from Skills Workflow, and a set of REST wrapper automations for creating proofs, managing reviewers, and getting one-time review links. The stage-sync description below is accurate and unchanged; the "Package Contents" and a new section below now reflect the full export. ### Description This article describes the integration between **ZiFlow** and `Skills Workflow`. ZiFlow is the online proofing tool where creative work is reviewed and approved. This integration closes the loop between the review and the job: when a proof moves in ZiFlow, the corresponding deliverable moves in Skills Workflow, automatically. Without it, someone has to watch ZiFlow and manually drag jobs through their stages — which is exactly the kind of double bookkeeping that makes job status untrustworthy. With it, the stage a job is in reflects what the reviewers actually did. --- ### Data Exchange Technology The integration is delivered as a **Marketplace automation**, not as a scheduled job. It is event-driven: 1. A reviewer acts on a proof in ZiFlow. 2. ZiFlow fires a webhook into Skills Workflow. 3. The automation reads the proof back from the ZiFlow API to confirm what happened. 4. The matching deliverable is transitioned to the corresponding stage. Because it is event-driven, the update is effectively immediate — there is no waiting for a nightly run. --- ### What Triggers a Stage Change | Event in ZiFlow | Stage applied in Skills Workflow | | --- | --- | | The proof finishes processing and is ready for review | **Proofing** | | A reviewer returns a decision of *changes required* | **Changes Required** | Any other proof event is ignored, so unrelated ZiFlow activity does not create noise in the job history. The automation also checks the deliverable's current stage before acting. If the job is already in the target stage, nothing happens — so a proof that generates several events does not produce a string of duplicate transitions. --- ### How Proofs and Deliverables Are Linked The link lives on the ZiFlow side. Each proof carries a **custom property group named "Skills Workflow"** containing a **DeliverableId** property, which holds the identifier of the deliverable in Skills Workflow. That property is what the automation uses to find the right job. A proof created without it cannot be matched, and the event is ignored. --- ### What the Agency Needs to Provide - A ZiFlow account with API access, and an API token. The token is stored in Skills Workflow as a configuration key and is never held in the automation itself. - A webhook configured in ZiFlow pointing at the Skills Workflow automation. - The **Skills Workflow → DeliverableId** custom property configured on the proofs, so proofs can be matched to jobs. - Confirmation of which stages in the agency's workflow correspond to *Proofing* and *Changes Required*. --- ### Package Contents The Marketplace package is larger than a single automation. As exported it includes: | Name | Type | Role | | --- | --- | --- | | Ziflow - Enqueue - Update proof status | Automation (v3) | The actual webhook target ZiFlow calls; enqueues the status update as background work | | Ziflow - Execute - Update proof status | Automation (v1) | Does the stage-sync logic described above | | Ziflow - Create Proof | Automation (v3) | Creates the client/job folder hierarchy in ZiFlow (if needed) and the proof itself | | Ziflow - Delete Proof | Automation (v1) | Deletes a proof | | Ziflow - Add Reviewer to Stage / Delete Reviewer from Stage / Update Reviewer by Id | Automation (v1) | Manage a proof stage's reviewers | | Ziflow - Get One Time Url | Automation (v2) | Generates a one-time review link for a reviewer and adds them to the internal/external review stage | | Ziflow - Get Proof by Proof Id / Get Proofs by document id | Automation (v2 / v1) | Look up proof(s) for display in Skills Workflow | | Ziflow - Get workflow templates | Automation (v1) | Lists ZiFlow workflow templates, for the Create Proof panel | | Ziflow - Job team mappings | Automation (v1) | Resolves which Skills Workflow team should review a given proof | | GetClientJobZiflowFolder | Query (v2) | Resolves the client's/job's existing ZiFlow folder ids for `Create Proof` | | Create Proof | Workspace (v15) | Panel on the Job for starting a new proof (pick workflow template, reviewers) | | Edit Proof | Workspace (v4) | Panel for editing an existing proof's details | | My Pending Proofs | Workspace (v2) | Panel listing proofs awaiting the current user | | Proofing Viewer | Workspace (v2) | Embeds the ZiFlow proof viewer directly in Skills Workflow | | Proofing | Workspace (v1 job / v12 job / v5 project) | Proof list panel, shown on Job and Project records | | Ziflow | System Parameter | Holds the ZiFlow API `token`, `url` and one-time-URL `expirationDays` | Source: files under `[Ziflow] [Integrations] ...` in the Marketplace export, listed in the Technical Reference below. --- ### Monitoring and Error Handling The automation records each execution, including the last time it ran and whether it succeeded. Failures are visible in the automation's log inside Skills Workflow. Because the flow is triggered by ZiFlow, an event that arrives while Skills Workflow is unavailable is not retried by the platform — ZiFlow's own webhook retry policy applies. --- ### Creating and Managing Proofs from Skills Workflow Beyond the inbound stage sync, this package lets people start and manage ZiFlow proofs without leaving Skills Workflow: - **Creating a proof** (`Ziflow - Create Proof`): resolves the job's (and if needed, its client's) ZiFlow folder via `GetClientJobZiflowFolder`, creating either folder in ZiFlow first if it doesn't exist yet (`POST https://api.ziflow.io/v1/folders`, folder id written back via `PUT /api/v3/documentUserFieldValues`), then creates the proof itself in that folder using the ZiFlow token from the `Ziflow` configuration key. - **Reviewers**: `Ziflow - Add Reviewer to Stage`, `Ziflow - Delete Reviewer from Stage` and `Ziflow - Update Reviewer by Id` are thin wrappers around ZiFlow's own `/v1/proofs/{id}/stages/{id}/reviewers` endpoints. `Ziflow - Get One Time Url` additionally adds a reviewer to the internal and external review stages and returns a one-time review link, expiring after the configured number of days. - **Viewing proofs**: `Ziflow - Get Proof by Proof Id` and `Ziflow - Get Proofs by document id` back the `My Pending Proofs`, `Proofing` and `Proofing Viewer` panels shown on Job/Project records. - **Workflow templates and team mapping**: `Ziflow - Get workflow templates` lists the templates available when starting a proof; `Ziflow - Job team mappings` resolves which Skills Workflow team should be assigned to review it. **Cross-reference:** the [Box](cloud-storage/box) integration includes `Box - Ziflow - Create temporary shared link`, which creates temporary Box shared links for files — used to feed file previews into these ZiFlow proofs. Source: `[Ziflow] [Integrations] Ziflow - Enqueue - Update proof status v3 (Automation) {Active}.json`, `[Ziflow] [Integrations] Ziflow - Execute - Update proof status v1 (Automation) {Active}.json`, `[Ziflow] [Integrations] Ziflow - Create Proof v3 (Automation) {Active}.json`, `[Ziflow] [Integrations] Ziflow - Delete Proof v1 (Automation) {Active}.json`, `[Ziflow] [Integrations] Ziflow - Add Reviewer to Stage v1 (Automation) {Active}.json`, `[Ziflow] [Integrations] Ziflow - Delete Reviewer from Stage v1 (Automation) {Active}.json`, `[Ziflow] [Integrations] Ziflow - Update Reviewer by Id v1 (Automation) {Active}.json`, `[Ziflow] [Integrations] Ziflow - Get One Time Url v2 (Automation) {Active}.json`, `[Ziflow] [Integrations] Ziflow - Get Proof by Proof Id v2 (Automation) {Active}.json`, `[Ziflow] [Integrations] Ziflow - Get Proofs by document id v1 (Automation) {Active}.json`, `[Ziflow] [Integrations] Ziflow - Get workflow templates v1 (Automation) {Active}.json`, `[Ziflow] [Integrations] Ziflow - Job team mappings v1 (Automation) {Active} - Automation.json`, `[Ziflow] [Integrations] GetClientJobZiflowFolder v2 (Query) {Active}.json`, `[Ziflow] [Integrations] Create Proof v15 (Workspace) {Active}.json`, `[Ziflow] [Integrations] Edit Proof v4 (Workspace) {Active} - Workspace.json`, `[Ziflow] [Integrations] My Pending Proofs v2 (Workspace) {Active}.json`, `[Ziflow] [Integrations] Proofing Viewer v2 (Workspace) {Active}.json`, `[Ziflow] [Integrations] Proofing v1 (Workspace) {Active} - Workspace.json`, `[Ziflow] [Integrations] Proofing v12 (Workspace) {Active}.json`, `[Ziflow] [Integrations] Proofing v5 (Workspace) {Active}.json`, `[Ziflow] [Integrations] Ziflow v1 (System Parameter) {Active}.json`. #### Open Questions - Two near-duplicate exports of `Ziflow - Job team mappings` differ only in a missing `/` in the ZiFlow URL template (`{{url}}{{proofId}}` vs `{{url}}/{{proofId}}`) — which is actually live is not determinable from the export. --- ### Good to Know - Stage names are configurable. If the agency renames the *Proofing* or *Changes Required* stages, the automation has to be updated to match. - The integration is one-way: ZiFlow drives Skills Workflow. Moving a job by hand in Skills Workflow does not change the proof in ZiFlow. - Only the two events above are handled today. Other proof decisions — approved, approved with changes — can be added by extending the automation. # AI --- ## Add Your Own Skills, Agents and Tools URL: https://documentation.skillsworkflow.com/docs/ai/extend Summary: Extend the AI with knowledge of your own way of working: skills that teach an agent your rules, agents built for your processes, and tools that reach your own systems and reports. The four agents Skills Workflow ships know the platform. They do not know your agency: your brief structure, your naming, your approval habits, the system you keep budgets in. Three things let you add that, and they stack. A **skill** is knowledge, an **agent** is a job to do with it, and a **tool** is something the agent can reach. | You want to | Add | |---|---| | Teach an agent a rule, a format or a process of yours | A **skill** | | Have an agent for a job of your own, with its own instructions and its own set of tools | An **agent** | | Let an agent reach one of your reports, or a system outside Skills Workflow | A **tool** | Work with your Skills Workflow consultant the first time. Nothing here is difficult, but an agent is only as good as the tools it is granted, and granting the wrong ones is how an agent becomes either useless or too free. ## Skills A skill is a written instruction set an agent can read when it needs it. It is how you stop repeating yourself: *"our briefs always open with the business objective"*, written once, is then true for everyone. A skill is a folder holding a `SKILL.md` file: a short header naming the skill and describing when to use it, then the instructions in plain Markdown. Longer material — a full format specification, a table of your codes, a worked example — goes in a `references/` folder beside it, and is read only when the agent needs that much detail. ``` $ai-agents/skills/ brief-house-style/ SKILL.md references/ SECTIONS.md ``` Skills live in your tenant's own file system, under `$ai-agents/skills/`. That is what makes them yours: one agency's skills are never visible to another, and you can change one without waiting for a release. **A skill is only used by the agents that list it.** Every agent definition carries the names of the skills it may read; a skill nobody lists is never advertised, and an agent listing a skill that is not there simply does not get it. When a skill stops taking effect, the name in the agent definition is the first thing to check. Agents are told each skill's name and description on every request, and fetch the body only when a request calls for it. Descriptions therefore matter: a skill described vaguely is a skill that never gets read. ## Agents An agent is a definition, not code. It carries: - **Name and description**, which is what the user sees in the panel's agent selector. - **Instructions**: how it behaves, what it always does, what it refuses. - **Skills** it may read. - **Tools**, which are what it can actually do. See [Tools](/docs/ai/ai-tools). - **Tools requiring approval**, the ones that stop and ask the user first. - **Suggested prompts** shown in an empty conversation. - **An icon** marking it in the list. - **A model**, named only when this agent needs a different one from the platform default. Once saved, it appears in the agent selector alongside the four that ship. There is no deployment step. Naming a model is worth doing when the job asks for it: a reasoning model for an agent that has to work something out, a cheaper one for an agent that only classifies or rewrites. Left unnamed, the agent runs on whatever the platform is configured with, which is what you want for most agents. Every agent you build honours the asking user's memories. That is not a tool you grant and cannot be switched off per agent; it is the user's own setting. Granting the memory tools decides only whether your agent may add to that store. See [AI Memories](/docs/ai/ai-memories). Four things worth getting right: - **Grant the smallest set of tools that does the job.** Leaving the tool list empty gives the agent the entire platform catalogue, including everything that writes. - **Put every writing tool on the approval list.** An agent that creates jobs without asking will eventually create one you did not want. - **Write the instructions as rules, not as encouragement.** "Never create a job without a client" holds. "Try to be careful about the client" does not. - **One agent, one job.** An agent asked to do everything picks the wrong tool. ### Agents that are not ours An agent can be pointed at an AI service you already run instead of at the platform's own model. The conversation is relayed to your endpoint and the reply comes back into the same chat panel, with the same history, the same attachments and the same agent selector. This is the route for a briefing model your agency has trained, or a service a client insists on. The agent's configuration carries the address, how the request is shaped, where in the response the answer sits, and the timeout. Attachments are passed as links; nothing is sent inline. Such an agent uses no platform skills or tools: it is your service answering. ## Tools Two ways to give agents capability beyond the built-in catalogue. ### Your own reports Your data extraction named queries can be exposed as tools, one tool per query. This is the shortest path to an agent that answers questions about your own numbers: the query already exists, already has the right joins, and is already role-checked. Turn analytics tools on for the agent, and list which queries it may reach. Left unlisted, it gets every query your tenant publishes — usually more than one agent needs. Every call is executed as the asking user, so a user refused a report in the platform is refused it here. Queries are read-only. See [Data Extraction API](/docs/build-and-extend/api/data-extraction-api) for what your tenant publishes. ### Your own systems An agent can be connected to an **MCP server**, a standard way of exposing a system's operations as tools. If a system you use already speaks it, or you can put a small service in front of one that does not, its tools appear to the agent alongside the platform's own. An MCP server is registered once for your tenant, with its address, and then named in each agent that should use it. Connection is per agent and explicit: an agent that does not name a server gets nothing from it. Connections are never shared between tenants. ## Rules and behaviour - Everything here is per tenant. Your skills, agents, MCP servers and their tools are yours alone. - Platform tools and data extraction queries always run as the signed-in user, so granting them never widens what a user can reach. - An MCP server is your own service and carries its own access. Whatever it can reach, every agent you connect it to can reach on behalf of every user of that agent. - A skill or agent is content, not a release. Change one and the next request uses it. - Version your agents and skills as you change them. Nothing enforces it, and without it a bad edit is hard to trace back. ## Related articles - [Tools](/docs/ai/ai-tools) - [Agents](/docs/ai/agents) - [AI Memories](/docs/ai/ai-memories) - [AI Actions](/docs/ai/ai-actions) - [Client Portals](/docs/ai/ai-portals) - [Data Extraction API](/docs/build-and-extend/api/data-extraction-api) --- ## AI Actions URL: https://documentation.skillsworkflow.com/docs/ai/ai-actions Summary: AI Actions put text assistance in the toolbar of every rich text editor. This page covers using them, and configuring the list your agency sees. AI Actions are the AI button in a rich text editor's toolbar. Instead of opening the chat panel, you pick an action from the toolbar and the text in the editor is rewritten in place. The actions in that menu are not fixed. **Your agency defines them.** A new tenant has an empty list and no menu until someone configures it. That is also what lets you ship actions worded for your own work. ## Availability Both settings live in **Maintenance > Configuration > System > Artificial Intelligence (AI)**: | Setting | What it does | |---|---| | Enable AI | Master switch for every AI feature | | Enable AI Actions | Shows the AI Actions button in rich text editors | With both on, the button appears in: - **Document briefs and descriptions** — the brief of a Job, Deliverable, Estimate, Contract, Request or any other document type. - **Feed posts** — the editor you compose a post in. ## How to use 1. Write something, or open a document that already has a brief. An action with an empty editor answers *Add content to the editor before running this action.* 2. Click the AI Actions button in the toolbar. 3. Pick an action, or use **Ask AI** and type the change you want in your own words. 4. The editor goes read-only while it works. 5. The result replaces what was there. A toast says *Text replaced. Click to undo.* `Ctrl+Z` / `⌘+Z` also puts the original back, and actions can be chained — rewrite, then shorten, then adjust the tone. Some actions open the [AI Assistant](/docs/ai/ai-assistant) panel instead of applying straight away, so you can iterate on the result and choose where to insert it. Which of the two an action does is part of its configuration. ## Working from a briefing template An action can be given the job type's **briefing template** as well as the editor's text. That is what turns rough notes into a structured brief: the action reads what you wrote, reads the template configured on the document's job type, and fills the template's sections from your notes. This only works where the job type has a briefing template configured. Without one, the action falls back to writing from your text alone. ## Configuration The list is the **AI Actions** grid in **Maintenance > Configuration > System > Artificial Intelligence (AI)**. Each row is one entry in the toolbar menu. | Column | What it does | |---|---| | ID | Identifies the action | | Label Key | The translation key used for the menu label. Use an existing key so the label is translated in every locale your users work in | | System Prompt | The instruction that sets how the action behaves | | User Prompt Template | What is sent for this action. `{{content}}` is the editor's text; `{{template}}` is the job type's briefing template | | Order | Position in the menu, ascending | | Entities | Restricts the action to certain document types. Leave empty to show it everywhere | | Custom Prompt | Makes this the action that asks the user what to do, rather than acting on its own | | Execution Mode | `popup` applies the result in place; `panel` continues in the AI Assistant | | Auto Send | Runs immediately instead of waiting for the user to confirm | | Server Tools | Tools the action may use. See [Tools](/docs/ai/ai-tools) | | Content Labels | Restricts the action to a particular editor | Actions run on the [Writing Agent](/docs/ai/agents/writing-agent) unless a row names a different agent, which is how an action can be pointed at an agent of your own. See [Add your own skills, agents and tools](/docs/ai/ai-extend). The translation keys already shipped for common actions include `Rewrite`, `MakeFriendly`, `MakeProfessional`, `MakeConcise`, `Summarize`, `FixGrammar`, `Compose`, `FillBriefTemplate` and `GenerateFromTemplate`. Referencing one of these in **Label Key** gives you a translated label without adding a translation of your own. ## Rules and behaviour - The result **replaces** the editor's content. Nothing is merged. - Actions answer in the language of the text you gave them. - An action that fails says *Unable to generate text right now. Please try again.* and leaves your text alone. - Nothing is saved until you save the document, so an unwanted result costs nothing. ## Related articles - [Writing Agent](/docs/ai/agents/writing-agent) - [AI Assistant](/docs/ai/ai-assistant) - [Tools](/docs/ai/ai-tools) - [Add your own skills, agents and tools](/docs/ai/ai-extend) --- ## AI Agents URL: https://documentation.skillsworkflow.com/docs/ai/agents Summary: The agents available in the AI Assistant, what each one can do, and how to pick the right one. AI Agents One agent for each kind of work. You pick an agent in the AI Assistant panel before you send a message. Each one carries a different set of tools, and that set is the whole of what it can do — so picking the right one is most of getting the right answer. Document Agent Create, update, duplicate, find and move jobs, deliverables and other documents. Writes briefs from a job type's template, edits custom fields, changes teams. "Create a job for the Northwind spring campaign" Explore → Workflow Agent Inspect and configure workflows — stages, transitions, actions, roles, motives, teams and mappings. "Show me the workflow for Deliverables" Explore → Workspace Agent Build and change workspaces and dashboards — components, layout, filters, data sources — and edit the files behind them when a change needs code. "Add a kanban panel to this workspace" Explore → Writing Agent Rewrite, shorten, translate or change the tone of any text. This is the agent behind AI Actions in the editor toolbar. "Rewrite this in a more professional tone" Explore → Getting a better answer Say what you want to end up with, not which button you think it needs. Name the client, project, job or workspace when you know it — that is what saves a round of questions. Leave the workspace or document context switch on when your request is about what is on screen. Attach the email, spreadsheet or image the request came from instead of retyping it. Read the approval card before approving. It lists exactly what is about to be written. These four are the agents Skills Workflow ships Your agency can add its own on top of them, with their own instructions, tools and knowledge. See Add your own skills, agents and tools. --- ## AI Assistant URL: https://documentation.skillsworkflow.com/docs/ai/ai-assistant Summary: The AI Assistant panel: how to open it, pick an agent, give it context, attach files, approve what it does, and manage chat history and memories. The AI Assistant is a chat panel that sits beside whatever you are working on. You type what you want in plain language, the assistant reads the screen you are on, and it answers or does the work. It does not open a separate screen and it does not lose your place. Inside the panel you choose an **agent**. Each agent is built for one kind of work and carries its own tools. See [Agents](/docs/ai/agents) for which one to pick. ## Availability The assistant is in **Preview**. The panel carries a `Preview` badge, and the product's own wording is worth repeating: *this feature is still under development, so its behaviour may change — review AI results before using them.* Four settings in **Maintenance > Configuration > System > Artificial Intelligence (AI)** control what your users see: | Setting | What it does | |---|---| | Enable AI | Master switch for every AI feature. When off, all AI features are hidden and no AI calls are made. | | Enable chat | Shows the AI Assistant panel and enables in-context AI editing without leaving the screen. | | Enable AI Actions | Shows the AI Actions button in rich text editors. See [AI Actions](/docs/ai/ai-actions). | | Enable flow logging | Adds **Download Flow Log** to the panel menu. Turn it on only while diagnosing a problem. | `Enable AI` must be on for any of the others to take effect. The panel is also hidden while the platform is in configuration mode. ## Open the assistant Click the floating assistant button in the bottom-right corner. It is draggable, so move it if it covers something. The panel opens on the right, and the button disappears while it is open. Collapsing the panel leaves a narrow strip you click to bring it back. ## Pick an agent Agent and context share one control, the sliders icon beside the message box: **Agent and context**. Open it and the **Agent** section names the agent in use. Click that name to see the full list with each agent's description, and pick another. Nothing is selected for you. Without a selection the panel refuses to send: *Select an agent before sending a message.* Each agent contributes its own suggested prompts to the empty conversation. Clicking one fills the message box. Opening a rich text editor while the assistant is on a different agent gets you an offer rather than a switch, naming what you are editing and the agent that suits it better. **Switch** changes agent, **Stay** keeps the one you have and is remembered for the rest of the session. On a conversation you have not typed in yet, the panel switches on its own and undoes it if you move away. ## Give it context The assistant does not read your whole account. It reads what you allow it to, and the **Context for this message** section of the same control lists every piece of it, grouped, with the reason each one is there. Each row appears only when there is something to send: | Group | Row | Sends | |---|---|---| | Current page | The document's name | The document open behind the panel | | Current page | The editor's name, with a character count | The text you are editing right now | | Job guidance | Brief instructions | The guidance that applies to this response. **Remove** drops it | | More context | The workspace's name | Its layout, filters and selection | | More context | Saved memories, with a count | What the assistant has learned about you | The switch on a row keeps that piece out of the request. The one on **Saved memories** is not a per-message override: it writes the same **Memory on** setting the memory screen shows. **Manage** opens that screen. See [AI Memories](/docs/ai/ai-memories). ## Attach files Drop a file onto the message box, or use **Attach file**. Each file becomes a chip above the box: images preview, everything else shows its type icon, and under the name you get the size, *Uploading…*, or the reason the file was refused. Remove one with the `×` on its chip. What happens next depends on the file, and the panel says which: *Images are analysed by the assistant. Other files are attached to the record.* An image is read and described. Any other file is held ready to be attached to a brief or posted to a feed when you ask, and it is carried onto a job or deliverable the same conversation creates. Attachments stay with the conversation. An agent asked to write a brief can still reach the file you attached two messages ago. These cannot be attached: - Files over your tenant's own upload limit, `FileSystemMaxSizeForUpload (MB)` in **Maintenance > Configuration > System > FileSystem**. Unset, the limit is 10 MB. - Email files, `.msg` and `.eml`. - Archives. - Programs and scripts, such as `.exe`, `.bat`, `.ps1`, `.sh` and `.jar`. An extension nobody recognises is still allowed. A `.psd` or an `.indd` attaches to a record perfectly well. ## Approve what it does Nothing is written on your behalf without a step you take. There are two gates, and which one you see depends on the agent. The [Document Agent](/docs/ai/agents/document-agent) shows an **Approval required** card naming the action and listing the arguments it is about to use: the job it will create, the stage it will move a document to, the people it will add to a team. You have three answers: - **Approve** runs the action. The card reads *Running*, then *Approved*. - **Deny** changes nothing. The assistant acknowledges it and offers the specific things you might want to change, such as *Change project* or *Change the name*. - **Make changes** lets you edit an argument on the card itself before approving. Some fields on the card are editable in place. A greyed-out value is a placeholder showing what the platform will fill in if you type nothing. Ignoring the card is safe. The action does not run, and nothing is lost if you type something else instead. The [Workflow Agent](/docs/ai/agents/workflow-agent) and the [Workspace Agent](/docs/ai/agents/workspace-agent) use the other gate: they build a **proposal**, show you what it changes, and wait for you to apply it. A proposal you have not applied can be reverted. Which actions raise an approval card is set per agent, so an agent your agency builds can gate as much or as little as you decide. See [Tools](/docs/ai/ai-tools). ## Answer a question When a request is missing something the assistant cannot guess, such as which client or which job type, it asks with a picker. Long lists come back partially, with *Showing the first results — refine your search to narrow them down.* Type in the picker's search box to narrow them. ## Follow what it is doing While the assistant works, the message it is writing carries the run above it, step by step. Each step names what is happening in your words rather than the tool's — *Searching for clients…*, *Loading job type template…*, *Creating job…* — and a count says how many steps the run took. Open a step to see the arguments it was called with and what came back. Use it when an answer surprises you. A brief written from the wrong template usually shows up here as the wrong template being loaded. ## Read an answer from your data When an agent answers from one of your data extraction queries, the rows are not left as a table inside a paragraph. The panel renders the result. - Rows that are documents come back as a list, grouped by urgency: **Overdue**, **Due today**, **Tomorrow**, **This week**, **Later**, **No date**. Counts along the top give you the totals, and clicking a row opens the document. - Rows that describe a breakdown come back as a chart with a table view beside it. A result that is both a list and a breakdown renders as both. - Long results are trimmed with a **Show all** control and a row count. - Ask two questions in one message and the panel shows the last answer, saying *2 queries ran — showing the last*. A query that cannot run says so: *The data query could not be run*, or *The assistant wrote a query this data does not support*. Which queries an agent may reach is set per agent. See [Tools](/docs/ai/ai-tools#your-data). ## Chat history Conversations are saved per user. Open **Chat History** from the panel menu to reopen one, and delete conversations there one at a time or several at once. Deleting a conversation cannot be undone. **New Chat** (the `+` in the panel header) starts a fresh conversation and keeps the current one in history. **Reset Chat** clears the conversation on screen. ## Memories The assistant carries what it has learned about you between conversations: a client you work with constantly, the language you write in, a job type you always pick. It also counts the client, project and job type you create documents for, and proposes them next time. Open **Manage Memories** from the panel menu to review all of it, switch a memory off, write one yourself, or turn memory off entirely. A remembered value is a suggestion: the assistant never reaches an approval card with one you have not confirmed. [AI Memories](/docs/ai/ai-memories) covers the screen, the two saving modes and the limits. ## Rules and behaviour - The assistant acts **as you**. It can only read and write what your own permissions allow, and a request for something you cannot see comes back empty rather than elevated. - Chat history is kept per user and per tenant. Two users never share a conversation, and the same user's conversations do not travel between tenants. - A very long conversation is compacted automatically instead of failing, and the earliest detail is the first to go. Start a **New Chat** when you change subject. - The conversation is not stored by the model service. Each request is answered and discarded there; the transcript you see is kept by Skills Workflow, on your user. - Answers are generated. Review anything before sending it to a client or acting on it. ## Related articles - [Agents](/docs/ai/agents) - [AI Memories](/docs/ai/ai-memories) - [Tools](/docs/ai/ai-tools) - [AI Actions](/docs/ai/ai-actions) - [Add your own skills, agents and tools](/docs/ai/ai-extend) --- ## AI for Agencies URL: https://documentation.skillsworkflow.com/docs/ai/overview Summary: What Skills Workflow AI does, where to find it, and how your agency shapes it around its own way of working. Skills Workflow · AI for Agencies AI built into the way your agency already works. Turn a client email into a job, a rough note into a finished brief, a question into an answer — in plain language, inside Skills Workflow. No new tool to learn, no prompt tricks. "Create a job for the Northwind spring campaign." Where it lives Three places — two you are already in, and one you hand to a client. The AI Assistant panel A chat panel beside whatever you are working on. It reads the screen you are on, does the work, and asks you to approve anything it is about to write. "Move this job to Client Approval." AI Actions in the editor A button in the toolbar of every rich text editor. Rewrite, shorten, change the tone, or fill your briefing template from notes — without leaving the field you are typing in. "Make this sound warmer before it goes out." Client Portals A page of a client's own, generated with AI and served from Skills Workflow at its own address. None of the platform's interface around it — the reader signs in as themselves, and the page reads live data through their own permissions. Nothing exported, nothing to keep in sync. "Build Northwind a page showing this quarter's deliverables." What your team can do today Less busywork. More of the work you were hired for. In the panel you pick an agent. Each one is built for a different kind of work. Create work in seconds Describe what a client asked for and get a job or deliverable created and filled in, with its brief written into your job type's template — not a blank form. "Create a deliverable for the Acme rebrand kickoff." Ask your data a straight question No dashboard to dig through. Ask about a project or a client and the assistant answers from your own reports, with your own permissions. "How is the Northwind retainer tracking this month?" Reshape how work flows Adjust stages, approvals and who signs off by describing the outcome you want, instead of walking through configuration screens. "Add a legal review step before Approved." Make the view fit each team Tune the panels and filters on a workspace, or build a new one, shaped around how a team actually works. "Add a board of this week's deliverables." Teach it your way of working Add skills that carry your rules, agents built for your processes, and tools that reach your own reports and systems. You stay in control Nothing is written without you saying so. How that works Creating or changing a document raises an approval card first, listing exactly what it will do. You can edit a value on that card before approving it. Denying it changes nothing, and the assistant offers what to adjust instead. A workflow or workspace change arrives as a proposal you apply, and can be reverted until you do. The assistant acts as you: it can never read or change what your own permissions do not allow. In preview The assistant carries a Preview badge. It is still under development, its behaviour may change, and results are generated — review them before acting on them or sending them to a client. Portals are new and still being built out. Read what is not there yet before you give a client the link. Start here AI Assistant — open it, give it context, approve what it does Agents — which one to pick AI Memories — what it remembers about you, and how to change it Tools — what an agent can actually do Client Portals — a page of a client's own, on live data Add your own skills, agents and tools AI that works the way your agency does. Humanized by Skills Workflow --- ## AI Memories URL: https://documentation.skillsworkflow.com/docs/ai/memories Summary: What the AI Assistant remembers about you, the screen where you review and change it, the two saving modes, and the limits on the store. The AI Assistant carries what it has learned about you from one conversation into the next: a preference you stated, a rule your team follows, the client most of your work belongs to. It uses that to fill in later requests instead of asking you the same question every time. Memories are yours. They are stored on your user, inside your tenant, and nobody else on your team can read them. Open **Manage Memories** from the panel menu. The screen has three tabs. ## Saved The facts, preferences and rules the assistant holds, newest first. A line above the list counts them against the 100 the store allows. Use the search box to find one in a long list. Each row carries the badges that apply to it: **Pinned**, **Written by you**, **Observed**, and **Off** for one you have switched off. Underneath it says *Learned on* and the date. Four controls sit on every row: - The switch turns the memory off. The row stays where it is, keeps its provenance, and stops being sent to the assistant. - **Pin memory** protects it. A pinned memory never expires and is never removed automatically. - **Edit memory** opens it for rewriting. - **Delete memory** removes it for good. **Add** writes one yourself. Type what the assistant should know, choose a **Type** of Preference, Rule or Fact, and pin it if you want it protected. A memory you write or edit is treated as confirmed: it never expires, and it is never dropped to make room for a newer one. ## What you usually do Every document you create through the assistant is counted against the client, project, department, job type and document type it used. This tab is the record of that, grouped by field, with each entity showing how many creations it accounts for and when you last used it. **Use always** makes an entity your assumed value for that field. Its row is badged **Always**, it leads its group, and it is proposed ahead of whatever you have simply used most often. **Stop using always** takes that back and keeps the accumulated count. **Forget** deletes the entry. The count goes with it and the entity stops being proposed. A creation is counted once. Nothing is added by reopening a conversation or by the assistant restating what it already did. ## Settings | Setting | What it does | |---|---| | Memory on | Master switch. With memory off nothing stored reaches the assistant, and nothing new is saved. Nothing is deleted. | | Save automatically and tell me | The assistant saves what it learns as it goes, and never hides that it is remembering. This is the default. Everything it saved is on the **Saved** tab, where you can switch it off or delete it. | | Ask before saving | Nothing is saved until you agree to that specific thing in the conversation. | | Use what I usually do to suggest values | Lets the counted entities above propose the client, project and job type while you create a document. You still confirm each one. | **Clear All** empties both the saved list and the counts. Your settings are left as they are. With memory switched off you can still edit and delete what is stored. Turning it off never leaves **Clear All** as the only way to change the store. ## How the assistant uses a memory A remembered value is a suggestion, never a decision you made. When the assistant fills a field from one, the field stays open: the remembered value arrives at the top of the choice list, and the request does not reach the approval card until you pick it. Memories hold names, not record IDs. The assistant looks the name up against real data before it uses it. A remembered project or job type is only offered once its client or department is settled. Until then you get the full list, scoped correctly. ## Rules and behaviour - The saved list holds at most 100 entries. Pinned memories and memories you wrote yourself are never removed to make room; once those alone fill the list, the assistant tells you it could not save a new one. - Up to 25 entities are counted per field. - Something the assistant inferred rather than being told expires after 90 days. Pinning it, editing it or confirming it keeps it. Counted entities never expire; using one again refreshes it. - Memories are per user and per tenant. Two people never share one, and the same person's memories do not travel between tenants. - Every agent honours your memories, including the ones your agency builds. Adding to the store is a tool: only agents granted it can write. See [Tools](/docs/ai/ai-tools#memory). - Switching memory off leaves everything in place. Switch it back on and the assistant picks up where it was. ## Related articles - [AI Assistant](/docs/ai/ai-assistant) - [Agents](/docs/ai/agents) - [Tools](/docs/ai/ai-tools) --- ## Analyzing Client Profitability URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/accounts-status/analyzing-client-profitability Summary: Compare income against costs to see margins, and the most and least profitable projects. ## Overview Provide an overview of client profitability by analyzing costs, income, margins, and relevant financial indicators across projects. ## Example prompt ``` Analyze the profitability of [Client / Client List] during [Period]. Compare project income against costs and identify the resulting profitability and margins. Highlight the most and least profitable projects, significant cost deviations, and any financial risks or opportunities. ``` ## Expected outcome A client profitability analysis showing income, costs, profitability, and margins for the selected period, identifying the most and least profitable projects, cost deviations, and potential financial risks. --- ## Asking Questions About Client Projects and Tasks URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/accounts-status/asking-questions-about-client-projects-and-tasks Summary: Get a consolidated view of progress, responsibilities, deadlines and outstanding work for a client. ## Overview Answer questions about projects and tasks across client accounts, providing a consolidated view of progress, responsibilities, deadlines, and outstanding work. ## Example prompt ``` Give me an overview of the current projects and outstanding tasks for [Client / Client List]. Include project status, task progress, overdue activities, upcoming deadlines, and responsible resources. Highlight the main issues and pending actions. ``` ## Expected outcome A consolidated overview of projects and outstanding tasks across the selected client accounts, including progress, overdue activities, upcoming deadlines, responsible resources, and pending actions. --- ## Asking Questions About Project Status URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/client-dashboards-and-forms/asking-questions-about-project-status Summary: Get a consolidated answer on project progress, milestones, risks and pending activities. ## Overview Answer questions about project status by consolidating relevant information on progress, milestones, risks, and pending activities. ## Example prompt ``` What is the current status of [Project / Client Projects]? Summarize the progress, completed and pending milestones, current risks, outstanding requests, and any issues that may affect the project timeline. Highlight the activities requiring attention. ``` ## Expected outcome A consolidated project status summary showing progress, completed and pending milestones, risks, outstanding requests, and issues affecting the project timeline. --- ## Brief Validator URL: https://documentation.skillsworkflow.com/docs/ai/agents/brief-validator Summary: Check whether a marketing brief has the information needed to prepare a client deliverable, using the client's own briefing rules. The Brief Validator reviews a marketing brief before work starts. It identifies the information that is missing or unclear and checks the brief against instructions that your agency maintains for that client. It gives feedback only; it does not create or change a deliverable. ## Availability An agency administrator must add the Brief Validator to the AI Assistant and enable the `get_client_brief_instructions` tool. To validate against client-specific rules, provide the client context with the brief. Without client context, the agent can give general feedback but cannot retrieve that client's instructions. ## How to use it 1. Open the [AI Assistant](/docs/ai/ai-assistant) and select **Brief Validator**. 2. Paste the brief and identify the client, or keep the relevant client context available. 3. Ask the agent to validate the brief. 4. Add the details it identifies, then ask it to validate the brief again. The result should focus on what is missing or unclear. It should not invent requirements or start creating the marketing asset. ## Add client briefing rules Create the instructions file in the selected commercial client's own file area. The `ai-instructions` folder sits directly under that client's root folder; place `brief-instructions.md` inside it. Replace this placeholder with a screenshot showing the client file tree, the ai-instructions folder and the brief-instructions.md file. Use the exact folder and file names shown in the image. This is a client-level file, not a shared tenant skill or an attachment in the chat. Keep the instructions focused on the information a usable brief needs. State explicitly when a value may be absent, such as `No call to action` or `No specific client rules`, so the agent does not ask for it unnecessarily. ## How the validation is assembled 1. The user selects **Brief Validator** and supplies a brief with client context. 2. The agent calls `get_client_brief_instructions` with that client. 3. The tool opens the client's file area, finds the `ai-instructions` folder and reads `brief-instructions.md`. 4. The tool returns the file content to the agent. The agent uses those rules to review the brief and returns the validation feedback. The tool looks only in this location. It does not scan other client files, chat attachments or the tenant's `$ai-agents/skills` folder. If the folder or file is missing, empty, or cannot be read, client-specific rules are not available and the agent can only give general brief-quality feedback. ## What the user receives With the example policy below, a complete brief returns `passed` with a summary. A brief with missing or unclear information returns `failed` and asks only for the details that are needed. In both cases, the agent does not create the deliverable. ## Example client instruction file The following is an example of a marketing-brief standard that an agency can adapt for a client. It is not a universal template: add the client’s own brand, legal and approval requirements where they apply. ```md # Brief instructions Validate whether the brief contains enough information to prepare a clear marketing deliverable. Do not create the deliverable until the brief passes. A brief must identify: 1. **Deliverable** — for example, one Instagram feed post, an email or landing page copy. 2. **Objective** — the result the deliverable should achieve. 3. **Audience** — who it is for. 4. **Main message** — the idea it should communicate. 5. **Call to action** — what the audience should do next, or `No call to action`. 6. **Client rules** — tone, required wording, restrictions or `No specific client rules`. 7. **Deadline** — a specific date or timing. Return `failed` when a required item is missing or unclear. List only those items and ask for the information needed. Return `passed` when the brief is complete, then summarize the approved brief. Do not invent missing details. ``` For example, `We need some content` is not a usable deliverable description. `We need one Instagram feed post` is specific enough for the validation to continue. ## Related articles - [AI Assistant](/docs/ai/ai-assistant) - [Document Agent](/docs/ai/agents/document-agent) - [Add your own skills, agents and tools](/docs/ai/ai-extend) --- ## Checking Contract Burn URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/resource-management/checking-contract-burn Summary: Compare contracted values against timesheets, workloads, costs and income to spot consumption trends and overruns. ## Overview Analyze contract consumption by comparing contracted values against timesheet records, workloads, costs, income, and time. Identify discrepancies, consumption trends, and potential overruns. ## Example prompt ``` Analyze the contract burn for [Client / Project]. Compare the contracted hours and amounts against the actual timesheet records, workloads, costs, and income. Include the percentage of contract consumption, remaining budget and hours, and any discrepancies or potential overruns. Highlight the main findings and areas requiring attention. ``` ## Expected outcome A consolidated contract burn analysis showing contracted versus actual consumption, remaining hours and budget, costs versus income, and workload information. The results highlight consumption trends, discrepancies, and potential overruns requiring attention. --- ## Checking Resource Availability URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/resource-management/checking-resource-availability Summary: Identify available resources by capacity, access permissions, typology groups and affinity timesheets. ## Overview Identify available resources based on capacity, access permissions, typology groups, and affinity timesheets. Provide an overview of resource availability for a specific period or project. ## Example prompt ``` Analyze resource availability for [Project / Team] during [Period]. Consider resource capacity, access permissions, typology groups, and affinity timesheets. Identify available resources, their remaining capacity, and any constraints that may affect their assignment. ``` ## Expected outcome A resource availability overview showing available capacity, access restrictions, typology groups, and affinity timesheet information for the selected period. The results identify resources available for assignment and any constraints affecting their availability. --- ## Client Portals URL: https://documentation.skillsworkflow.com/docs/ai/portals Summary: A client portal is a page of its own, generated with AI, served from Skills Workflow behind your users' session and reading live platform data through their own permissions. A client portal is a web page of its own, served from Skills Workflow at `/portal/{client}/{portal}/`. Its own layout, its own charts, its own words. It is not a workspace and not a dashboard: the platform's interface is not loaded around it, so the page can look like anything. It also sits **inside your session**. Someone opening a portal signs in as themselves, and the page reads live Skills Workflow data through their own permissions. Nothing is exported, copied or kept in sync. Portals are written with AI. You describe the page you want, and the platform ships a skill that tells the agent everything it needs about the environment: what data it can reach, how to call it, and what the sandbox forbids. Portals are new and still being built out. Read [What is not there yet](#what-is-not-there-yet) before planning a rollout to client users. ## What a portal is for - A view for one client that does not fit any workspace: their own reporting page, in their own words - A screen shaped around one job, in a layout the platform's components do not produce - A page you hand someone as a link, without teaching them the platform ## How it works Each portal lives in a folder, and the folder structure *is* the registry. Publishing a portal is putting its files somewhere; removing it is deleting them. There is no list to keep in step. The address has exactly two segments: the client, then the portal. Both may contain only lowercase letters, numbers and hyphens, and must start with a letter or number. ``` /portal/{client}/{portal}/ ``` Portals are stored in your tenant's own file system, under a `Portals` folder, as `{client}/{portal}/index.html` plus whatever else the page needs. The file system's own permissions apply: someone who cannot read the folder does not get the portal. ### Signing in A portal request without a session is sent to a sign-in screen and returned to the portal afterwards. From then on the page is served under that session. The page itself never receives an access token. When it calls the API, the call goes to Skills Workflow's own address and the server attaches the credentials. The portal reads data as the signed-in user, and cannot read anything they could not. ### What the page can reach A portal is given a small SDK. Through it the page can: - Call the Skills Workflow API v2 and v3 as the signed-in user - Read the signed-in user's profile, available on the very first paint with no call - Run your **data extraction named queries**, the same ones behind your reports, which is what fills a table or a chart - Draw the platform's own avatars for a user, client, client group or company - End the session Named queries are filtered, sorted and paged in the database before a row is returned, and are read-only. Each one is role-checked, so a user who is not granted a report is refused it in a portal too. ### The sandbox A portal runs under a content security policy that is deliberately tight: - No scripts from anywhere else. Everything the page needs is inside the portal folder. - No calls to anywhere but Skills Workflow. - Images must come from Skills Workflow, or be embedded in the page. - Google Fonts is the one external source allowed, for its stylesheets and font files. Charts are therefore drawn in the page itself. ## Getting a portal built 1. **Say what the page is for and who opens it.** One client, one audience, one question the page answers. 2. **Name the data.** Which report, which figures, which records. A portal reads what your data extraction queries publish, so a question no query answers needs the query first. 3. **The portal is generated.** The `client-portal` skill gives the agent the whole contract: the SDK, the sandbox, the query grammar, and the rule that no endpoint or column may be invented. Where a fact cannot be established, the agent says so. 4. **Review it against the states, not just the happy path.** A portal must render an empty answer, a refused one and an unreachable service as three different things. Open it as a user who is *not* granted the report and check what they see. 5. **Publish it** to the `Portals` folder in your tenant's file system, under `{client}/{portal}/`. ## Rules and behaviour - Every request is authorised. There is no anonymous portal. - A portal belonging to another tenant is indistinguishable from one that never existed. Portals and clients cannot be enumerated across tenants. - Signing out deletes the session cookie. As on the rest of the platform, it does not invalidate the token itself. - Republishing a file that already exists must replace it as a new version. Uploading it again creates a second file of the same name, and the portal may keep serving the old one. - A portal is served read-only. It has no storage of its own; anything it saves goes through the API. ## What is not there yet These are known and worth deciding on before portals go to client users: - **There is no publishing tool.** A portal is published by creating its folders and uploading its files. - **A portal is not scoped to its client.** Access today is "has a session, and the folder exists". The client segment in the URL does not restrict who may open it, so any signed-in user can open any client's portal if they know its address. Restricting the portal folders by role is the mechanism to use in the meantime. - **Who may write to the `Portals` folder is a security boundary.** A portal runs script in the browser of everyone who opens it. Treat write access to that folder as you would treat deploying code. - **A build that emits absolute paths will not work.** A portal is served under its own path; a page whose assets are addressed from the site root loses all of them. Generate relative paths, or configure the base path at build time. ## Related articles - [Add your own skills, agents and tools](/docs/ai/ai-extend) - [Data Extraction API](/docs/build-and-extend/api/data-extraction-api) - [AI Assistant](/docs/ai/ai-assistant) --- ## Consolidated Portals Across Multiple Clients URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/accounts-status/consolidated-portals-across-multiple-clients Summary: Monitor several client accounts from a single consolidated view. Planned — not available yet. This use case describes where the assistant is headed, not what it can do today. ## Overview Provide a consolidated overview of multiple client portals, enabling users to monitor the status of several accounts from a single view. ## Example prompt ``` Give me a consolidated overview of the portals for [Client List]. Summarize the status of each client's projects, outstanding requests, risks, and critical issues. Highlight the accounts requiring attention and provide links to the relevant client portals where available. ``` ## Expected outcome A consolidated overview of multiple client portals, showing each client's project status, outstanding requests, risks, and critical issues, with links to the relevant portals where available. --- ## Create a Job from a Client Email URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/projects-and-jobs/creating-a-job-from-a-client-email Summary: Paste a client request into the AI Assistant, check the Job it proposes, and review the created Job in chat. ## Overview Copy a client's request into the AI Assistant and ask it to create a Job. The assistant can use the names and scope in the email to find the client and project, suggest a title, department and Job Type, and prepare a brief. Confirm any suggested matches and approve the Job after reviewing its details. This example starts with text pasted into chat. The email, agency records and Job number below are illustrative. The assistant reads the pasted request, proposes where the work belongs and prepares the Job for approval. } > I received this from our General Motors contact. Can you create a Job and full brief from it? From: Sofia, General MotorsSubject: Dealer locator page for the EV campaign Hi team, for the General Motors – 2026 Global EV Campaign project, we need a page that helps visitors find a nearby dealer. Please introduce the electric vehicle range, make the dealer locator the main call to action, and include a way to book a test drive. Follow the campaign visual direction. Can you start this work? I found General Motors and the named campaign project. I suggest a Job in Digital with the Web Design Job Type, titled “GM EV Campaign – Dealer Locator Page”. I’ll use the email’s scope in the brief. Is that the work you want to create? Yes. Keep the dealer locator as the main call to action, and include the test-drive booking. The Job details are ready for review. Review the proposed details and brief in the approval card before creating the Job. I reviewed the proposal and selected Approve. The Job has been created. ## Related articles - [Turn a Campaign Brief into a Job](/docs/ai/use-cases/projects-and-jobs/creating-a-job-using-a-briefing-template) - [AI Assistant](/docs/ai/ai-assistant) - [AI Agents](/docs/ai/agents) --- ## Creating an Estimate From Files URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/contracts-estimates-and-purchase-orders/creating-an-estimate-from-files Summary: Extract scope, deliverables, resources and rates from an attached file to prepare an estimate. Planned — not available yet. This use case describes where the assistant is headed, not what it can do today. ## Overview Extract relevant information from uploaded files, such as briefs, spreadsheets, or project documentation, and use it to prepare an estimate. ## Example prompt ``` Create an estimate for [Client / Project] using the attached files. Extract the project scope, deliverables, required resources, estimated hours, rates, costs, and any relevant conditions. Organize the information into an estimate with a breakdown of the deliverables, resources, quantities, rates, and total amounts. Highlight any missing information or assumptions that require confirmation. ``` ## Expected outcome A structured estimate generated from the attached files, containing the extracted project scope, deliverables, resources, estimated hours, rates, costs, and total amounts, with missing information and assumptions flagged for confirmation. --- ## Creating an Estimate From Instructions URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/contracts-estimates-and-purchase-orders/creating-an-estimate-from-instructions Summary: Generate an estimate from a described scope, deliverables, resources and rates. Planned — not available yet. This use case describes where the assistant is headed, not what it can do today. ## Overview Generate an estimate based on user-provided instructions, including the required scope, deliverables, resources, rates, and other relevant information. ## Example prompt ``` Create an estimate for [Client / Project] based on the following instructions: [Describe the project scope, deliverables, required resources, estimated hours, applicable rates, costs, and any relevant conditions.] Prepare the estimate with a breakdown of the deliverables, resources, quantities, rates, and total amounts. Highlight any missing information or assumptions that need confirmation before finalizing it. ``` ## Expected outcome A structured estimate based on the provided instructions, including deliverables, resources, quantities, rates, and total amounts, with missing information and assumptions clearly identified for confirmation. --- ## Discussing a Project Delay Notification URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/client-dashboards-and-forms/discussing-a-project-delay-notification Summary: Investigate why an activity was delayed using its comments, replies, descriptions and attached files. ## Overview Investigate a project delay notification by reviewing comments, replies, descriptions, and attached files. Summarize the available context and initiate a discussion to clarify the cause of the delay. ## Example prompt ``` Review the delay notification for [Project / Task]. Analyze the notification details, comments, replies, descriptions, and attached files to understand why the activity was delayed. Summarize the available information and start a discussion asking the relevant team members to clarify the cause of the delay and its impact on the project timeline. ``` ## Expected outcome A contextual summary of the delay, based on the notification details, comments, replies, descriptions, and attachments, together with a discussion initiated to clarify the cause and its impact on the project timeline. --- ## Discussing a Resource Overrun Notification URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/resource-management/discussing-a-resource-overrun-notification Summary: Investigate a resource overrun notification using its comments, replies, descriptions and attached files. ## Overview Start a discussion about a resource overrun notification by reviewing the available context, including comments, replies, descriptions, and attached files. ## Example prompt ``` Review the notification about the resource overrun in [Project / Resource]. Analyze the notification details, comments, replies, descriptions, and attached files to understand the situation. Summarize the likely causes and start a discussion with the relevant context, asking for clarification on the overrun and possible next steps. ``` ## Expected outcome A contextual summary of the resource overrun, incorporating the available notification details, comments, replies, descriptions, and attachments, together with a discussion initiated to clarify the cause and possible next steps. --- ## Discussing Estimate Scenarios Before Creation URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/contracts-estimates-and-purchase-orders/discussing-estimate-scenarios-before-creation Summary: Compare alternative scopes, resources, rates and budgets before creating an estimate. ## Overview Explore and compare alternative estimate scenarios before creating an estimate, considering different scopes, resources, rates, costs, and budgets. ## Example prompt ``` Help me explore different estimate scenarios for [Client / Project] before creating the estimate. The project scope is: [Describe the project scope and requirements.] Compare the following scenarios: [Describe the alternative scopes, resources, hours, rates, or budget constraints.] For each scenario, summarize the required resources, estimated hours, costs, and total amount. Highlight the main differences, assumptions, and potential risks to help me evaluate the alternatives before creating the estimate. ``` ## Expected outcome A comparison of alternative estimate scenarios, showing the resources, estimated hours, costs, and total amounts for each option, together with the main differences, assumptions, and potential risks to support the evaluation before creating the estimate. --- ## Document Agent URL: https://documentation.skillsworkflow.com/docs/ai/agents/document-agent Summary: Create, update, duplicate, find and move jobs, deliverables and other documents by describing what you need, with an approval card before anything is written. The Document Agent does the work you would otherwise do through forms: creating a job, writing its brief, filling custom fields, changing who is on the team, moving it to the next stage. You describe the outcome; it works out which records that means and asks you to approve before it writes. It is the agent to pick for anything that ends in a document existing or changing. ## What it can do - Create a job or deliverable, with its brief written from the job type's briefing template - Update an existing job's title, priority, effort, business value, dates, job type, and its plannable, blocked and timesheet flags - Duplicate a Job, Deliverable, Project, Estimate or Request, optionally carrying over the description, team and custom field values - Read and rewrite a document's brief - Read and set custom field values - Add and remove team members, across several roles in one change - Move a document to another workflow stage - Search any document type, and open one in a popup or navigate to it - Attach a file you dropped into the chat to a brief, or post it to the document's feed For the full list of tools behind these, see [Tools](/docs/ai/ai-tools). ## How to use it 1. Open the [AI Assistant](/docs/ai/ai-assistant) and select **Document Agent**. 2. Describe what you want. Name the client, project or job if you know it. 3. Answer the pickers it raises. When a name matches more than one record, it asks which one rather than guessing. 4. Read the approval card and approve, deny, or edit a value on the card first. Working from a document already open on screen, leave the **Document** context switch on. The agent then knows which document you mean without being told. ### Creating a job Describe the work in the same words you would use to a colleague, and include anything the brief should say. ``` Create a job for Northwind, spring campaign, artwork for the launch email. Deadline end of next week. ``` The agent resolves the client, project, department and job type, asking you where a name is ambiguous. Before creating, it reads the job type's briefing template and writes your description into that structure, so the brief follows your agency's format rather than arriving as a paragraph. The approval card shows the resolved fields and the drafted brief; edit the title or description there if either is wrong. Where you have not named a client, project or job type, the one you create most of your work for is offered first, as a *Yes, use …* confirmation rather than a value already filled in. Turn that off with **Use what I usually do to suggest values** in [AI Memories](/docs/ai/ai-memories#settings). Change your mind about the client mid-flow and the project, department and job type you had already settled are asked again. Each of those belongs under the one above it, and the values available change with it. ### Duplicating a document Ask for a copy and say what should differ: ``` Duplicate this job, but this one is for YouTube. ``` The agent reads the source brief, rewrites the name and the brief for the stated difference, and leaves everything else inherited. Client, project, department and job type always come from the original and cannot be changed here. It raises a question about whether to carry over the description, the team and the custom field values unless you already said. A duplicate creates a new document. To fix a title or a brief on a document that already exists — including the copy you just made — ask for the change; do not ask for another duplicate. ### Moving a stage ``` Move SKILLS0059S1492 to Client Approval. ``` The agent lists the transitions actually available on that document right now, you pick one, and it asks for approval. If the transition requires a comment, a reason, hours, a file or extra fields, it collects them first. ## Rules and behaviour - Everything that writes asks for approval first, and denying it changes nothing. - The agent works with your permissions. A document you cannot see, it cannot find. - Re-scoping is not supported: a document's client, project, department and business object type are fixed once it exists. - Custom fields are written by their configured field, never by the label on screen, so a renamed label does not break a change. - `Generate from template` results depend on the job type having a briefing template configured. Without one, the brief is written from the conversation alone. ## Related articles - [AI Assistant](/docs/ai/ai-assistant) - [Tools](/docs/ai/ai-tools) - [Workflow Agent](/docs/ai/agents/workflow-agent) - [Writing Agent](/docs/ai/agents/writing-agent) - [AI Actions](/docs/ai/ai-actions) --- ## Finding Pending Tasks and Actions URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/projects-and-jobs/finding-pending-tasks-and-actions Summary: Get a prioritized list of overdue tasks, upcoming deadlines and blocked activities. ## Overview Provide a consolidated overview of tasks and pending actions, highlighting overdue activities, upcoming deadlines, priorities, and responsibilities. ## Example prompt ``` Show me the tasks and pending actions for [Project / Client / Team] during [Period]. Include overdue tasks, upcoming deadlines, blocked activities, task priorities, and responsible resources. Organize the results by priority and deadline, and highlight the actions that require immediate attention. ``` ## Expected outcome A prioritized list of pending actions, including overdue tasks, upcoming deadlines, blocked activities, task priorities, and responsible resources, highlighting the actions requiring immediate attention. --- ## Finding the Best Client Dashboard or Portal URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/client-dashboards-and-forms/finding-the-best-client-dashboard-or-portal Summary: Identify the most suitable dashboard or portal for sharing project information with a client. ## Overview Identify the most suitable dashboard or portal for sharing project information with clients, based on the information they need to access. ## Example prompt ``` What is the best dashboard or portal to share project information with [Client]? I need a view that provides visibility into project status, progress, risks, contract burn, and pending requests. Identify the most relevant option and explain what information it provides. ``` ## Expected outcome The most relevant dashboard or portal for sharing project information with the client, including the information it provides about status, progress, risks, contract burn, and pending requests, with a link where available. --- ## Finding the Best Dashboard for Account Allocation URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/accounts-status/finding-the-best-dashboard-for-account-allocation Summary: Identify the most suitable dashboard for monitoring resource allocation across client accounts. ## Overview Identify the most suitable dashboard for monitoring resource allocation across client accounts and projects. ## Example prompt ``` What is the best dashboard to monitor resource allocation across [Client List]? Identify the most relevant dashboard and explain how it helps track resource allocation by client, project, and team. ``` ## Expected outcome The most relevant dashboard for monitoring resource allocation across client accounts, including an explanation of how it presents allocation by client, project, and team, with a link where available. --- ## Finding the Best Dashboard for Allocation URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/resource-management/finding-the-best-dashboard-for-allocation Summary: Identify the most suitable dashboard for monitoring resource allocation. ## Overview Identify the most suitable dashboard for monitoring resource allocation and provide access to the relevant view. ## Example prompt ``` What is the best dashboard to monitor resource allocation across [Team / Project / Period]? Identify the most relevant dashboard and explain what allocation information it provides. ``` ## Expected outcome The most relevant dashboard for monitoring resource allocation, including its purpose and the allocation information available through it, with a link to the dashboard where available. --- ## Finding the Best Dashboard for Resource Requirements URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/resource-management/finding-the-best-dashboard-for-resource-requirements Summary: Identify the most suitable dashboard for comparing planned resource demand against available capacity. ## Overview Identify the most suitable dashboard for monitoring resource requirements and comparing planned demand against available capacity. ## Example prompt ``` What is the best dashboard to monitor resource requirements for [Project / Team / Period]? Identify the most relevant dashboard and explain how it helps track resource demand, required capacity, and potential resource gaps. ``` ## Expected outcome The most relevant dashboard for monitoring resource requirements, showing how it supports the analysis of resource demand, required capacity, and potential resource gaps, with a link to the dashboard where available. --- ## Finding the Best Dashboard for Utilization URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/resource-management/finding-the-best-dashboard-for-utilization Summary: Identify the most suitable dashboard for monitoring resource utilization and capacity usage. ## Overview Identify the most suitable dashboard for monitoring resource utilization, including workload distribution and capacity usage. ## Example prompt ``` What is the best dashboard to monitor resource utilization across [Team / Department / Period]? Identify the most relevant dashboard and explain how it helps monitor workload, capacity usage, and resource utilization. ``` ## Expected outcome The most relevant dashboard for monitoring resource utilization, with an explanation of how it presents workload distribution and capacity usage, and a link to the dashboard where available. --- ## Identifying Project Delays URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/projects-and-jobs/identifying-project-delays Summary: Identify delayed projects, milestones and tasks, and the documented reasons and impact. ## Overview Identify delayed projects, milestones, and tasks by analyzing deadlines, progress, dependencies, and available status information. Highlight the causes and potential impact of delays where documented. ## Example prompt ``` Identify delays across [Project / Client Projects]. Analyze project deadlines, milestones, task progress, dependencies, and current status. Highlight overdue tasks, delayed milestones, and activities that may affect the project timeline. Include the documented reasons for delays, their potential impact, and the items requiring attention. ``` ## Expected outcome A consolidated overview of delayed projects, milestones, and tasks, including overdue activities, documented reasons for delays, potential impacts on project timelines, and items requiring attention. --- ## Identifying Resource Scarcity URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/resource-management/identifying-resource-scarcity Summary: Identify current or upcoming resource shortages across projects, and where additional capacity may be required. ## Overview Identify current or upcoming resource shortages across projects. Highlight resource gaps, affected projects, and periods where additional capacity may be required. ## Example prompt ``` Identify resource shortages across current and upcoming projects during [Period]. Highlight the projects, roles, or typology groups affected, the periods of insufficient capacity, and the gap between required and available resources. Identify the areas where additional resources may be needed. ``` ## Expected outcome A list of current and upcoming resource shortages, identifying affected projects, roles, and typology groups, together with the periods of insufficient capacity and the additional resources required. --- ## Monitoring Critical Activities Across Accounts URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/accounts-status/monitoring-critical-activities-across-accounts Summary: Identify overdue tasks, upcoming deadlines and blocked activities across several client accounts. ## Overview Identify critical activities across multiple client accounts, highlighting overdue tasks, upcoming deadlines, blocked activities, and other issues requiring attention. ## Example prompt ``` Show me the critical activities across [Client List]. Identify overdue tasks, upcoming deadlines, blocked activities, and projects at risk. Organize the results by client and priority, including the responsible team or resource and the relevant project or task links where available. ``` ## Expected outcome A prioritized overview of critical activities across client accounts, including overdue tasks, upcoming deadlines, blocked activities, responsible resources, and links to the relevant projects or tasks. --- ## Providing Clients With an Online Project Status Portal URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/client-dashboards-and-forms/providing-clients-with-an-online-project-status-portal Summary: Give a client a consolidated online view of project status, contract burn, risks and pending requests. ## Overview Provide clients with a consolidated online view of project status, contract burn, risks, and pending requests through the relevant client portal. ## Example prompt ``` Show me the best client portal to provide [Client] with an online overview of their projects. Include project status, contract burn, risks, and pending requests. Identify the most relevant portal and explain what information is available to the client. ``` ## Expected outcome A client portal providing an online overview of project status, contract burn, risks, and pending requests, with the relevant information organized for client access. --- ## Receiving Notifications About Project Delays URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/client-dashboards-and-forms/receiving-notifications-about-project-delays Summary: Get proactively alerted to delayed milestones, overdue tasks and their expected impact. Planned — not available yet. This use case describes where the assistant is headed, not what it can do today. ## Overview Identify project delays and schedule-related issues that require attention, including affected projects, milestones, and expected impacts. ## Example prompt ``` Show me the project delays and schedule-related issues affecting [Client / Projects]. Identify delayed milestones, overdue tasks, affected deliverables, and expected impacts on project timelines. Include the current status and any available explanation for each delay. ``` ## Expected outcome A list of project delays and schedule-related issues, identifying affected milestones, tasks, deliverables, expected impacts, and available explanations for each delay. --- ## Receiving Notifications About Resource Issues URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/resource-management/receiving-notifications-about-resource-issues Summary: Get proactively alerted to resource overruns, unexpected assignments and deviations from planned capacity. Planned — not available yet. This use case describes where the assistant is headed, not what it can do today. ## Overview Identify resource-related issues such as resource overruns, unexpected resource assignments, and deviations from planned capacity. Provide an overview of the issues requiring attention. ## Example prompt ``` Show me the resource-related issues that require attention across [Projects / Team]. Identify resource overruns, unplanned or unexpected resource assignments, and deviations from planned capacity. For each issue, provide the affected project, resource, relevant dates, and a summary of the situation. ``` ## Expected outcome A consolidated list of resource-related issues requiring attention, including resource overruns, unexpected assignments, and deviations from planned capacity, with the affected projects, resources, dates, and issue details. --- ## Resource Management Overview Portal URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/resource-management/resource-management-overview-portal Summary: Get a consolidated, priority-ordered overview of the resource issues that need attention. ## Overview Provide a consolidated overview of critical resource-related information, highlighting issues that require attention and enabling navigation to the relevant dashboards, projects, or resources. ## Example prompt ``` Give me an overview of the most critical resource management issues across [Team / Department]. Highlight resource overruns, capacity shortages, unexpected assignments, and projects requiring immediate attention. Organize the information by priority and provide links to the relevant dashboards, projects, or resource details where available. ``` ## Expected outcome A consolidated overview of critical resource management issues, organized by priority, with direct navigation to the relevant dashboards, projects, and resource details where available. --- ## Roadmap URL: https://documentation.skillsworkflow.com/docs/ai/roadmap Summary: What Skills Workflow AI already does, what is being finished, and what is planned next. Roadmap What is here, and what is coming. Everything under Delivered is in the product now and has a page describing how to use it. Everything below that is directional: the sequence is what we intend, not a commitment to a date. Delivered In the product today. Chat, everywhere Ask where you are working AI Assistant — a panel beside any screen, reading the workspace or document you are on AI Actions — text assistance in the toolbar of every rich text editor Memories — the assistant remembers what you told it, and you can clear it Data Ask your data a straight question Your reports as tools — the assistant answers from your own data extraction queries, with your own permissions Documents and processes Do the work, not the forms Create and change documents — jobs, briefs, custom fields, teams, duplicates Move a document — without leaving the chat Understand and change a workflow — stages, transitions, approval paths Briefs that follow your template — nothing starts blank Building Idea to set-up, fast Workspaces and dashboards from a sentence Client Portals — a page of its own, generated with AI, reading live data Your own skills, agents and tools In progress Partly here, being finished. Directional · subject to change Files & contents Read what is already written Attach a file to a request and have it read — available now in the assistant Summarize a long discussion, and everything attached and decided on a piece of work Creation Beyond one job at a time Jobs and deliverables — available now Whole projects and estimates from a description or an email Suggesting the right people for the work, not only applying who you named Client portals Ready for client users Publishing a portal without uploading its files by hand Scoping a portal to the client it belongs to Planned Where we are taking it next. Directional · subject to change Reach Work from your chat Talk to Skills Workflow from WhatsApp Then from Microsoft Teams Know The problem finds you Say once what you want warning about — margins, overhead, a slipping deadline — and be told, with the evidence attached Client status and sentiment at a glance Create Less retyping Client reports generated from the work already recorded Reading a cost sheet or a scanned document straight into document lines Have a request? If there is a workflow you wish AI already handled, tell your Skills Workflow contact — this roadmap is shaped directly by what agencies ask for. Some of it you do not have to wait for: an agent of your own, with your rules and your tools, is something you can build today. See Add your own skills, agents and tools. --- ## Tools URL: https://documentation.skillsworkflow.com/docs/ai/tools Summary: The catalogue of tools an agent can be given: what each one lets the agent read or change, which ones write to your account, and how tools are granted per agent. An agent on its own can only talk. What lets it look something up, create a job or move a document is a **tool**. An agent's tools are the whole of what it can do: an agent without `create_job` cannot create a job, however you ask. This page is the catalogue. Read it to know what an existing agent is capable of, and to decide what to grant an agent you are building in [Add your own skills, agents and tools](/docs/ai/ai-extend). ## How tools are granted Every agent definition carries a `tools` allow-list. Listing tool names restricts the agent to those; leaving the list empty gives it the whole platform catalogue below. `get_current_time` is added to every agent and needs no entry. Two further sets are opt-in and are not part of `tools`: - **Your data extraction queries**: set `useAnalyticsTools`, and narrow with `analyticsTools`. - **Your own MCP servers**: list them in `mcpServers`. Both are covered in [Add your own skills, agents and tools](/docs/ai/ai-extend). ## Tools that write These change data. Put every one of them on the agent's `toolsRequiringApproval` list so the user sees an approval card before the tool runs. See [AI Assistant](/docs/ai/ai-assistant#approve-what-it-does). `create_job` · `update_job` · `duplicate_document` · `update_document_brief` · `update_document_custom_fields` · `update_team_members` · `execute_workflow_transition` · `create_timesheet_entry` Everything else on this page reads, apart from the three memory tools, which write only to the asking user's own memory store. ## Platform tools These run on the server, against the Skills Workflow API, as the signed-in user. ### Finding a record | Tool | What the agent can do | |---|---| | `resolve_client` | Find a client from a name the user typed, ranked by relevance | | `resolve_project` | Find a project from a name | | `resolve_department` | Find a department, scoped by project, client and business object type | | `resolve_job_type` | Find a job type within a department | | `list_clients` | List clients, optionally filtered by name | | `list_projects` | List projects, filtered by name, client, product, contract or request | | `list_departments` | List departments the user can see, optionally narrowed by project | | `list_job_types` | List job types, filtered by department, client, project or document type | | `list_document_types` | List document types | | `list_assignment_types` | List the team roles a document type accepts | | `get_project_by_id` | Read full project details | | `search_users` | Find users by name, email or username | | `get_current_user` | Read who is asking | | `get_current_time` | Read the current date and time | The `resolve_*` tools are what turn *"the Northwind retainer"* into a record. When more than one candidate matches, the assistant asks you to pick. ### Documents and jobs | Tool | What the agent can do | |---|---| | `get_job_by_number` | Open a job by its number | | `search_documents` | Search any document type — projects, jobs, estimates, contracts, expenses, bills, purchase orders, requests, credit notes, supplier invoices | | `create_job` | Create a job or deliverable from project, business object type, department, job type, dates and title | | `update_job` | Edit an existing job's title, priority, effort, business value, dates, job type and its plannable, blocked and timesheet flags | | `duplicate_document` | Copy a Job, Deliverable, Project, Estimate or Request, optionally carrying over its description, team and custom field values | `update_job` changes only the fields passed. It cannot re-scope a document: client, project, department and business object type are fixed once a document exists. ### Briefs | Tool | What the agent can do | |---|---| | `get_document_brief` | Read a document's brief | | `update_document_brief` | Write a document's brief | | `get_job_type_brief_template` | Read the briefing template configured on a job type, so a brief follows your structure | | `get_client_brief_instructions` | Read the client's own brief-writing instructions | Together these are what produce a structured brief instead of a paragraph. The agent reads the job type's template and the client's instructions first, then writes into that scaffold. #### Client brief instructions `get_client_brief_instructions` is read-only. It takes the selected commercial client's ID, opens that client's own file area, and follows this route: ```text Client root folder → ai-instructions folder → brief-instructions.md ``` It returns the Markdown content of that file to the agent. The tool does not search the rest of the client files, chat attachments or the tenant's `$ai-agents/skills` folder. The folder and file must exist in the client file area, and the file must contain text. If either is missing, empty or cannot be read, the tool has no client instructions to return. An agent can then use its general briefing guidance, but it cannot validate against client-specific rules. See [Brief Validator](/docs/ai/agents/brief-validator) for the setup, an example instruction file and the expected validation result. ### Custom fields | Tool | What the agent can do | |---|---| | `get_document_custom_fields` | List a document's custom fields with their labels and current values | | `update_document_custom_fields` | Set one or more custom field values | ### Teams | Tool | What the agent can do | |---|---| | `get_document_team` | Read who is on a document's team | | `update_team_members` | Add and remove team members | One `update_team_members` call carries every change the user asked for, across as many roles as they named, and lands in the document's feed as a single entry. ### Workflow | Tool | What the agent can do | |---|---| | `list_workflow_transitions` | List the transitions available on a document right now | | `execute_workflow_transition` | Move a document to another stage | There is no default transition. The agent lists what is available, you pick, and then it asks for approval. ### Time | Tool | What the agent can do | |---|---| | `create_timesheet_entry` | Log time. Without a user, it logs against the person asking | ### Your data | Tool | What the agent can do | |---|---| | `execute_named_query` | Run one of your data extraction named queries and return rows | | `analytics_{query}` | One tool per named query your tenant publishes, granted through `useAnalyticsTools` | These are what answer *"how is this client tracking this month"* without a dashboard. Every query is filtered, sorted and paged in SQL before a row is returned, is read-only, and is scoped to the asking user's permissions — a user refused a report in the platform is refused it here too. Both tools take the query's own parameters plus a `queryBuilder`, and that is where filtering, sorting, paging and column selection happen: `filters`, `orderBy`, `fields`, `skip` and `take`. There is no aggregation. A total or a breakdown comes from a query written that way, not from the agent asking for one. Every call is bounded. An agent that names no row count gets 50 rows, and 500 is the ceiling on any count it does ask for. A query author's own row limit lowers both. The panel renders what comes back as a list, a chart or both. See [AI Assistant](/docs/ai/ai-assistant#read-an-answer-from-your-data). The query catalogue is per tenant. See [Data Extraction API](/docs/build-and-extend/api/data-extraction-api) for which queries exist and what each carries. ### Memory | Tool | What the agent can do | |---|---| | `save_memory` | Remember a preference, fact or record the user named | | `update_memory` | Correct something remembered earlier | | `delete_memory` | Forget something | These write to the asking user's own store and nowhere else. Whether they write at all is the user's decision: with **Memory on** switched off, a save is refused and the agent is told so. With **Ask before saving**, the agent must get the user's agreement in the conversation first. Forgetting always works. Every agent honours a user's memories, granted these tools or not, because reading them is not a tool. Users manage the store under **Manage Memories** — see [AI Memories](/docs/ai/ai-memories). ### Chat interface | Tool | What the agent can do | |---|---| | `gen-ui.emit_custom_event` | Push a card or a custom payload into the chat | | `gen-ui.emit_custom_prompt` | Offer a follow-up prompt the user can tap | Neither changes any data. ## Browser tools These run in the user's browser instead of on the server, because they need the screen the user is looking at. They are granted per agent and cannot be listed in `tools`. | Tool | What the agent can do | |---|---| | `OpenDocument` | Open a document in a preview popup, or navigate to it | | `AttachFileToDocument` | Attach a file the user dropped into the chat to a document's brief | | `PostFileToFeed` | Post to a document's feed, with a file | | `SDK_List` | List the SDK methods available to it | | `SDK_Invoke` | Call one of them | | `Workspace_Get`, `Workspace_List` | Read a workspace definition | | `Workspace_Validate`, `Workspace_Apply` | Check a workspace change, then apply it | | `CustomTable_List`, `CustomTable_Get`, `CustomTable_Validate` | Read and check custom table definitions | | `Integration_Get`, `Integration_List`, `Integration_Validate` | Read and check integration workflows | | `GetBriefingTemplates`, `GetBriefingTemplateContent`, `ResolveJobTypeBriefingTemplate` | Read briefing templates from the editor | | `GetTransitionRequirements` | Read what a transition needs before running it: a comment, a motive, hours, a file, user fields | | `GetJobByNumber`, `SearchDocuments` | Look up a job or search documents from the screen the user is on | | `SearchWorkflowStageTransitions` | List the transitions available on a document right now | | `ExecuteWorkflowTransition` | Move a document to another stage. Writes | | `GetDocumentBrief`, `UpdateDocumentBrief` | Read and write a brief from inside the editor. `UpdateDocumentBrief` writes | ## What tools cannot do - **They never exceed your permissions.** Every call carries the signed-in user's identity. An agent asked for a report the user is not granted gets refused, exactly as the user would be. - **They never act as someone else.** The user a tool acts for is taken from the session, never from something the agent decides. - **Data extraction is read-only.** No named query writes. ## Related articles - [Agents](/docs/ai/agents) - [AI Assistant](/docs/ai/ai-assistant) - [AI Memories](/docs/ai/ai-memories) - [Add your own skills, agents and tools](/docs/ai/ai-extend) - [Data Extraction API](/docs/build-and-extend/api/data-extraction-api) --- ## Tracking Pending Proposals and Approvals URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/accounts-status/tracking-pending-proposals-and-approvals Summary: Find proposals awaiting approval, who is holding them up, and for how long. ## Overview Identify proposals awaiting approval, their current status, the time spent pending, and any available information explaining why approval has not yet been granted. ## Example prompt ``` Show me all proposals for [Client / Client List] that are still awaiting approval. Include the proposal name, amount, submission date, current approval status, pending approver, and time spent waiting. Review available comments, descriptions, and related information to identify any documented reasons for the delay. ``` ## Expected outcome A list of proposals awaiting approval, including amounts, submission dates, pending approvers, and waiting times, together with any documented reasons for the pending status. --- ## Turn a Campaign Brief into a Job URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/projects-and-jobs/creating-a-job-using-a-briefing-template Summary: See how the AI Assistant turns a campaign request into a Job and organizes its brief with a Job Type template. ## Overview Describe the work to the AI Assistant in your own words. It can find matching client and project records, infer a department, Job Type and title from the request, and organize the brief with the Job Type's template. Review the proposed Job before approving its creation. The agency, Job number and Web Design template in this example are illustrative. Available records and briefing sections depend on your configuration. The assistant collects the Job details, prepares the brief using the selected Job Type's template and presents the creation for approval. } > We need a global website for General Motors’ 2026 electric vehicle campaign, under our “General Motors – 2026 Global EV Campaign” project. Can you set up the Job and write the full brief? The site should introduce the campaign, show the electric vehicle range, explain the main campaign message and guide visitors to the next step. I’ve attached a visual reference. I found General Motors and the named campaign project. Because you asked for a website, I suggest Digital, the Web Design Job Type and the title “GM 2026 EV Campaign – Global Website”. I can organize your requirements in its briefing template. Are those Job details right? Yes, use Digital and Web Design. Keep that title. The Job details are ready for review. Review the proposed Job details in the approval card before creating it. I reviewed the proposal and selected Approve. The Job has been created with a brief organized in the Web Design template. I kept your requested campaign content and visual reference. The final wording of the campaign message still needs to be supplied. ## How the request becomes a structured brief This comparison illustrates how the request can fill an agency's Web Design briefing template. The section names are an example, not fixed Skills Workflow fields. The assistant carries over what the user supplied and leaves the campaign message wording open for confirmation. ## Related articles - [Create a Job from a Client Email](/docs/ai/use-cases/projects-and-jobs/creating-a-job-from-a-client-email) - [AI Assistant](/docs/ai/ai-assistant) - [AI Agents](/docs/ai/agents) --- ## Updating Rate Cards URL: https://documentation.skillsworkflow.com/docs/ai/use-cases/contracts-estimates-and-purchase-orders/updating-rate-cards Summary: Update rate card values and see the impact on estimates, contracts and project costs. Planned — not available yet. This use case describes where the assistant is headed, not what it can do today. ## Overview Update rate card information based on user instructions or an attached file, identifying the changes and their potential impact on estimates and project costs. ## Example prompt ``` Update the rate card [Rate Card Name] based on the following instructions or attached file: [Describe the rates to be updated, the applicable resources or typology groups, the effective date, and any relevant conditions.] Identify the existing and proposed rates, summarize the changes, and highlight any potential impact on estimates, contracts, or project costs. Flag any information that requires confirmation before applying the changes. ``` ## Expected outcome An updated rate card reflecting the requested changes, with a summary of existing and proposed rates, applicable resources or typology groups, effective dates, and potential impacts on estimates, contracts, and project costs. Any information requiring confirmation is highlighted. --- ## Workflow Agent URL: https://documentation.skillsworkflow.com/docs/ai/agents/workflow-agent Summary: Inspect and configure workflows — stages, transitions, actions, roles, motives, teams and mappings — by describing the change you want. The Workflow Agent is for the lifecycle itself: how a document moves from one stage to the next, who may move it, and what has to happen on the way. Use it to understand a workflow you inherited, or to change one without walking through the configuration screens. It configures workflows. Moving one particular document through its stages is the [Document Agent](/docs/ai/agents/document-agent). ## What it can do - Explain an existing workflow — its stages, the transitions between them, and what each transition requires - Add, change or reorder stages - Create transitions between stages, and set what a transition asks for - Adjust approval paths and who is allowed to perform a transition - Change the reasons and actions attached to a transition - Read and set the teams and mappings a workflow uses ## How to use it 1. Open the [AI Assistant](/docs/ai/ai-assistant) and select **Workflow Agent**. 2. Name the workflow, or the document type it belongs to. 3. Ask it to show you the workflow first when you are changing one you did not build. 4. Describe the change as an outcome — *"nobody outside Legal can approve this"* rather than a list of fields. Start by reading before writing: ``` Show me the workflow for Deliverables. ``` Then change one thing at a time: ``` Add a legal review step before Approved, and only Legal can move it out. ``` ## Rules and behaviour - Ask for one change at a time. A broad request comes back as a proposal to work through, not as a stack of applied edits. - The agent validates a change before applying it, and tells you when a change is refused rather than applying part of it. - A workflow change affects every document already in that workflow. Read what it proposes before approving. - Stage types are system-defined. See [Workflow stage types](/docs/administration/workflows/stage-types) for what each one means. ## Related articles - [AI Assistant](/docs/ai/ai-assistant) - [Document Agent](/docs/ai/agents/document-agent) - [Tools](/docs/ai/ai-tools) --- ## Workspace Agent URL: https://documentation.skillsworkflow.com/docs/ai/agents/workspace-agent Summary: Build and change workspaces and dashboards by describing what you want — components, layout, filters and data sources — and edit the files behind them when a change needs code. The Workspace Agent builds and changes workspaces and dashboards. Describe the view you want and it produces a change you review before it is applied — a new panel, a different filter, a chart reading from somewhere else, a whole workspace from scratch. It works at two levels, and moves between them on its own: - **The workspace definition** — components, layout, data sources, filters, and how components react to each other. This is most work. - **The files behind a workspace** — the individual JavaScript functions and JSON configuration a workspace is built from. This is where a change goes when no setting expresses it: a custom column formatter, a function that filters by status, a bug in a component's setup. ## What it can do - Create a workspace, or add a component to one — grids, forms, charts, indicators, boards - Change a component's configuration, its filters and its layout - Wire a component to a data source, and wire components to react to one another - Read a custom table's schema or an integration workflow, and validate a change to either - Read and edit the JavaScript and JSON files behind a workspace - Show you exactly what changed before you save ## How to use it 1. Open the workspace you want to change, so the agent has it in context. 2. Open the [AI Assistant](/docs/ai/ai-assistant), select **Workspace Agent**, and leave the **Workspace** context switch on. 3. Describe one change. 4. Review the proposal, then apply it. You can revert a preview that is not what you meant. Keep requests to one panel, widget or layout area at a time. A broad request comes back as a suggestion to start somewhere specific. ``` Add a kanban panel of this week's deliverables, grouped by stage. ``` ``` Change this grid to show a filter row, and default it to my department. ``` For a change in code, name the component and the behaviour: ``` Fix the column setup in the estimates grid — the total column shows blank for rows with no lines. ``` The agent reads the relevant files first, tells you what it plans to change, and then changes it. ## Rules and behaviour - Nothing is saved until you apply it. A proposal can be reverted while you are looking at it. - The agent validates a workspace change before applying it and reports a rejection rather than half-applying it. - Editing the files behind a workspace is close to the code. It suits studio leads and technical administrators; for layout, filters and widget settings, stay with the plain-language route above. - The agent works with your permissions, so it can only reach workspaces you can already open. ## Related articles - [AI Assistant](/docs/ai/ai-assistant) - [Tools](/docs/ai/ai-tools) - [Workspaces](/docs/build-and-extend/workspaces) --- ## Writing Agent URL: https://documentation.skillsworkflow.com/docs/ai/agents/writing-agent Summary: Rewrite, shorten, translate or change the tone of any text, in the chat panel or straight inside the editor you are typing in. The Writing Agent works on text. Give it something you have written and say what is wrong with it — too long, too blunt, in the wrong language, not clear enough — and it gives the text back changed. It is also the agent behind [AI Actions](/docs/ai/ai-actions), the wand button in every rich text editor. Reach for the chat panel when you want to explain what you are after; use AI Actions when one of the standard changes is what you need. ## What it can do - Rewrite for clarity - Shorten while keeping the point - Change tone — warmer, more formal, more direct - Fix grammar - Translate - Summarize - Compose from a description - Fill a briefing template with content you have already written ## How to use it 1. Open the [AI Assistant](/docs/ai/ai-assistant) and select **Writing Agent**. 2. Paste the text, or leave the **Document** context switch on to work on the brief of the document behind the panel. 3. Say what you want changed. Naming the reader helps: *"this goes to the client, make it warmer."* 4. Read the result before using it. Chaining works. Rewrite first, then shorten, then adjust the tone. ## Rules and behaviour - It answers in the language you wrote in unless you ask for another. - It changes wording, not facts. Check any figure, date or name that matters before the text goes out. - In the editor, an action replaces what is there. `Ctrl+Z` / `⌘+Z` puts it back. ## Related articles - [AI Actions](/docs/ai/ai-actions) - [AI Assistant](/docs/ai/ai-assistant) - [Document Agent](/docs/ai/agents/document-agent) # Trust, Security & Compliance --- ## Asset Inventory Program URL: https://documentation.skillsworkflow.com/docs/trust/access%20%26%20asset%20management/asset-inventory-program Summary: SKILLS0018OP084 Explains the purpose and benefits of maintaining an asset inventory within Skills Workflow. SKILLS0018OP084 ## Overview Explains the purpose and benefits of maintaining an asset inventory within Skills Workflow. Describes procedures to secure and track company equipment. ## Key Topics ### Device Enrollment Devices are enrolled via Intune for centralized management and security. ### Asset Tracking Procedures for documenting and tracking company assets, including lost or stolen devices. ### Security and Documentation Steps to secure assets and maintain accurate records to reduce risks. ## Document Preview --- ## BCP and DRP URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/bcp-drp Summary: SKILLS0018OP042 Details Skills Workflow’s business continuity and disaster recovery plans designed to ensure minimal downtime. SKILLS0018OP042 ## Overview Details Skills Workflow’s business continuity and disaster recovery plans designed to ensure minimal downtime. ## Key Topics ### Critical Systems and Disaster Declaration Outlines critical systems, criteria for declaring a disaster, and contact procedures. ### Recovery Processes Provides specific recovery steps for databases, storage, integrations, and global services across Azure regions. ### Communication and Coordination Defines communication and coordination processes during disaster recovery. ## Document Preview --- ## Change Management and System Adoption URL: https://documentation.skillsworkflow.com/docs/trust/service%20quality%20%26%20change%20management/change-management-adoption Summary: SKILLS0018OP082 Covers deployment strategies, support methods, and ADKAR change management principles used to drive adoption within Skills Workflow. SKILLS0018OP082 ## Overview Covers deployment strategies, support methods, and ADKAR change management principles used to drive adoption within Skills Workflow. ## Key Topics ### Deployment and Support Details deployment approaches and support models. ### Change Management Principles Emphasizes branding, integration, and engagement measurement using ADKAR. ### Communication and Stakeholders Includes communication plans and stakeholder roles to reinforce change. ## Document Preview --- ## Cyber Security FAQ URL: https://documentation.skillsworkflow.com/docs/trust/cyber-security-faq Summary: This document provides answers to the most frequently asked questions regarding our Cyber Security policies, practices and certifications. ## Overview This document provides answers to the most frequently asked questions regarding our Cyber Security policies, practices and certifications. It is intended to help clients and stakeholders understand how Skills Workflow ensures the confidentiality, integrity and availability of its systems and client data. --- ## Certifications and Compliance - **Does Skills Workflow hold third-party certifications such as ISO 27001 or SOC 2?** Yes. We have third-party security certificates. - **Are there security audits or penetration tests?** Yes. We perform annual third-party penetration testing and conduct regular static code analysis. - **Do you follow a formal SDLC with security reviews?** Yes. Security is integrated throughout our SDLC, including secure code reviews and vulnerability remediation before production deployment. --- ## Data Protection - **Is client data used in development or testing environments?** No. Client data is never used outside the production environment. - **Are development, test and production environments segregated?** Yes. We maintain strict separation of environments to reduce risk and ensure stability. - **Is data at rest encrypted?** Yes. Microsoft Azure uses Transparent Data Encryption (TDE) to secure all data at rest. - **Is data in transit encrypted?** Yes. All data in transit is encrypted using HTTPS and TLS 1.3. - **Is client data logically separated from other clients’ data?** Yes. Each client’s data is logically segregated to ensure privacy and isolation. - **Are backups encrypted and securely managed?** Yes. Backups are encrypted and managed by Microsoft Azure according to their compliance and security standards. --- ## Access Control - **Are user access rights reviewed periodically?** Yes. Access rights are reviewed regularly and adjusted based on role and business need. - **Is there a password policy enforced across systems?** Yes. Our password policy defines minimum complexity, expiration, and reset requirements. --- ## Employee Awareness & HR Policies - **Are employees required to attend security awareness training?** Yes. All employees complete security onboarding and attend periodic training sessions. - **Are HR policies reviewed and approved by management?** Yes. HR policies are maintained, reviewed and approved at multiple levels including HR, department heads and executive leadership. - **Are background checks part of the hiring process?** Yes. All new hires undergo screening as part of the recruitment process. --- ## Secure Development - **Are applications reviewed from a security perspective before release?** Yes. All releases follow security review checkpoints defined in our SDLC. - **Is secure coding practiced and verified?** Yes. We use static code analysis and perform secure code reviews. - **What happens if vulnerabilities are found before deployment?** Any high or critical vulnerability will block promotion to production until resolved. - **Are infrastructure and OS updates managed internally?** No. Infrastructure updates are managed by Microsoft Azure. Clients configure their own features within the application. --- ## Policies and Governance - **Do you have an asset management policy?** Yes. All employee equipment and assets are tracked and governed by internal policy. - **Is information classified based on sensitivity or regulatory requirements?** Yes. Internal documentation follows a tiered classification model. Clients are responsible for classifying their data within the system. - **Are there formal change management controls?** Yes. All changes to the codebase follow a documented change control process. Client-side configurations are managed by each client independently. --- ## Additional Questions? If your organization requires a custom security questionnaire, specific policy documents or third-party attestations, please contact our compliance team at [security@skillsworkflow.com](mailto:security@skillsworkflow.com). --- ## GDPR Compliance URL: https://documentation.skillsworkflow.com/docs/trust/data%20protection%20%26%20privacy/gdpr-compliance Summary: SKILLS0018OP035 Outlines Skills Workflow’s approach to GDPR, covering personal privacy, user rights, consent, data processing, and transparent policies. SKILLS0018OP035 ## Overview Outlines Skills Workflow’s approach to GDPR, covering personal privacy, user rights, consent, data processing, and transparent policies. ## Key Topics ### Encryption and Breach Notification Details encryption methods, breach notification procedures, and audit processes. ### Roles and Responsibilities Clearly defines IT and Data Protection Officer (DPO) roles for compliance management. ### User Control and Staff Training Emphasizes user control over personal data, continuous compliance monitoring, and staff training on GDPR requirements. ## Document Preview --- ## Incident Management URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/incident-management Summary: SKILLS0018OP074 Describes Skills Workflow’s processes for identifying, escalating, and resolving critical system incidents. SKILLS0018OP074 ## Overview Describes Skills Workflow’s processes for identifying, escalating, and resolving critical system incidents. ## Key Topics ### Incident Identification and Escalation Specifies triggers, escalation paths, and communication protocols. ### Incident Response Team Details the 24/7 incident response team schedules and responsibilities. ### Stakeholder Updates Includes structured updates during outages or maintenance. ## Document Preview --- ## Information Security Policy URL: https://documentation.skillsworkflow.com/docs/trust/data%20protection%20%26%20privacy/information-security-policy Summary: SKILLS0018OP073 Defines scope, responsibilities, and controls to secure data and systems at Skills Workflow. SKILLS0018OP073 ## Overview Defines scope, responsibilities, and controls to secure data and systems at Skills Workflow. ## Key Topics ### Access Control and Encryption Covers access management, encryption, and secure development. ### Monitoring and Compliance Highlights monitoring, audits, and threat detection measures. ### Staff Training Regular security training and compliance awareness for employees. ## Document Preview --- ## Log4shell URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/other%20issues/Log4shell Summary: In this article, we clarify our clients about the newly found CVE-2021-44228 also known as “log4shell” and how it impacts (or not) SkillsWorkflow. In this article, we clarify our clients about the newly found CVE-2021-44228 also known as "log4shell" and how it impacts (or not) SkillsWorkflow. ## Impact Summary On the 9th of December, the digital world took notice of a new vulnerability called Log4shell. This vulnerability is a library created in Open Source where any person can contribute to its development. Being this an Open Source, the code is available for free and used by many people. More specifically on Java applications and Apache servers. However, this vulnerability does not expose Skill Workflow, taking into account that we do not use Java in any of our services or use any Apache services. ## Mitigation We recommend all customers review their own code and services for any use of this component and upgrade or apply one of the mitigations to keep themselves secure. 1. If possible upgrade to log4j version 2.15 2. If you are using log4j version 2.10 or above, and cannot upgrade, then add the following property to the Java command line: -Dlog4j2.formatMsgNoLookups=true Alternatively, you can set the following environment variable: LOG4J_FORMAT_MSG_NO_LOOKUPS=true 3. For all versions, but specifically for those below 2.10 remove the affected class from the classpath: zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class --- ## Production Access Report URL: https://documentation.skillsworkflow.com/docs/trust/access%20%26%20asset%20management/production-access-report Summary: SKILLS0018OP062 Monthly audit report detailing access logs, permissions, and production changes. SKILLS0018OP062 ## Overview Monthly audit report detailing access logs, permissions, and production changes. ## Key Topics ### Access Control Ensures only authorized personnel access production environments and databases. ### Approval and Evidence Includes approval processes and access evidence to confirm compliance. ### Compliance Confirmation Verifies adherence to security protocols. ## Document Preview --- ## RCA - Mitigated - All Regions - 02-05-2019 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2019-05-02%20RCA-Mitigated-All-Regions Summary: Between 19:29 UTC and 22:35 UTC on 02 May 2019, users may have experienced errors when using Skills Workflow V1 or V2 on all our regions (West Europe, Brazil… ### Impact summary Between 19:29 UTC and 22:35 UTC on 02 May 2019, users may have experienced errors when using Skills Workflow V1 or V2 on all our regions (West Europe, Brazil South, East US, and Southeast Asia). Around 21:40 UTC the error rate was negligible and only observable in the East US region. All other regions were operating normally. ### RCA Skills Workflow is a multi-service distributed system running on Microsoft Azure on multiple regions. As such, Skills Workflow internal and external services need to communicate with each other and with Azure services on which our platform relies. The cause for this outage was due to a problem on the Azure platform that impacted network connectivity in all Azure regions which in turn impacted several services used by our platform. More info on the Azure issue can be tracked with Azure issue number: R50C-5RZ # Next steps We understand the impact these issues have on our customers that's why Skills Workflow relies on world-class Azure services and employ all industry best practices so our customers can rely on our platform 24/7. Azure will be taking steps to avoid issues like this in the future. --- ## RCA - Mitigated - APIv2 - East US - 28-09-2022 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2022-09-28-RCA-Mitigated-APIv2-East-US Summary: On 28 September 2022, between 20:25 UTC and 22:46 UTC, many customers experienced errors or extreme delays accessing the Web Application, APIv2, and other… ### Impact summary On 28 September 2022, between 20:25 UTC and 22:46 UTC, many customers experienced errors or extreme delays accessing the Web Application, APIv2, and other APIs on our East US region. The incident response team noticed that SQL Database resource usage was extremely high and that was causing the API to respond very slowly. The extreme resource usage on the database was caused by a customer workload and the response team started to restart backend services in an attempt to abort the faulty workload, but without success. As the next measure a SQL Database resource tier upgrade was initiated which lasted for about 30 minutes. After that the faulty workload was aborted and response times started getting back no normal. ### RCA In the course of the investigation to the causes of this incident, the engineering team identified several operations related to user notifications and leave updates that could, in some occasions, consume extremely high database resources. During this incident a bulk import forced a very high number of these operations leading to exhausting SQL Database resources, thus causing extremely high response times and errors. ### Next steps Our costumers rely on Skills Workflow and we understand the impact these incidents have and that's why we are committed to continuously improve our platform. The team has already improved database resource consumption on the identified operations and is continuously working to find more resource consumption issues to improve the platform performance and reliability. Additionally, measures were put in place to avoid a single workload to consume all database resources. --- ## RCA - Mitigated - ApiV2 - File System - West Europe - 19-02-2021 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2021-02-19%20RCA-Mitigated-ApiV2-File-System-West-Europe Summary: Starting 19 February 2021 at around 13:37 UTC until 16:05 UTC, some users experienced errors and degraded response time performing some operations on our West… ### Impact summary Starting 19 February 2021 at around 13:37 UTC until 16:05 UTC, some users experienced errors and degraded response time performing some operations on our West Europe region. Affected operations were saving and opening some documents, viewing files, among others. Upon investigation, the team found that one replica of a backend service responsible for managing the file system became unhealthy after an automatic infrastructure platform update. About 0.3% of all requests were effected. ### RCA After investigation, the team found that a file system service upgrade rolled out on 18th of February at 9:54 contained a bad configuration parameter. Unfortunately, that bad parameter did not affect the service when it was rolled out and the new service version kept working healthy until Azure made a platform update on the 19th from 13:37 to 13:47 on one of the nodes running an instance of the file system service. That node became unhealthy and all requests to it resulted in error (about 30% of all service requests). The team quickly mitigated the issue by manually fixing the bad configuration parameter. ### Next steps We understand the impact these issues have on our customers and that's why Skills Workflow is committed to continuously improving our platform. Since this incident the file system service team has already globally rolled out a fix with the correct parameter. Service health checking was improved on the load balancer so that unhealthy nodes are removed from rotation until they recover. Monitoring will be improved to make sure that we catch these issues earlier. --- ## RCA - Mitigated - APIv2 - West Europe - 02-01-2023 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2023-01-02-RCA-Mitigated-APIv2-West-Europe Summary: On 02 January 2023, between 11:00 UTC and 12:00 UTC, some customers experienced timeout errors when moving documents to a different status or creating new… ### Impact summary On 02 January 2023, between 11:00 UTC and 12:00 UTC, some customers experienced timeout errors when moving documents to a different status or creating new documents in our West Europe region. After some analysis, the incident response team identified timeout errors on SQL database calls in the API v2. They were not consistent over time, and occurred in different operations. These timeout errors, in some cases, led to incomplete operations and incoherent data, including documents with status changed but without the corresponding post entry. ### RCA Skills Workflow is highly dependent on several data services; Azure SQL Database is our main data store technology, so any issue with this service has a high impact on our services. After further investigation into the problem, it was found that SQL Database service had some connectivity and timeout issues during the incident time span due to Azure platform maintenance, thus resulting in less responsiveness overall. ### Next steps Our customers rely on Skills Workflow and we understand the impact these incidents have, and that's why we are committed to continuously improving our platform. Although there is already a retry policy when connecting to our Azure SQL database, some further actions are needed to assure more stability. We have planned to redefine this retry policy, ensuring that all database dependent operations are resilient to transient errors, including database timeouts and connectivity issues. --- ## RCA - Mitigated - APIv2 - West Europe - 12-12-2023 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2023-12-12-RCA-Mitigated-APIv2-West-Europe Summary: On 12 December 2023, between 09:10 UTC and 09:50 UTC, approximately, some customers experienced delays and missing executions in some services over the system… ### Impact summary On 12 December 2023, between 09:10 UTC and 09:50 UTC, approximately, some customers experienced delays and missing executions in some services over the system in our West Europe region. Search, analytics and automations experienced timeout errors and high latency when executing. The incident response team was quickly notified due to several alerts over these services. After some investigation, it was verified that some services were not responding correctly in our Azure infrastructure due to connectivity issues. During the incident, the Azure Management Portal was not working properly, giving errors when accessing some resources in the West Europe region. Some alerts were also lost during the incident. The team engaged Azure Support, and it was confirmed that Azure was investigating an incident in the West Europe region regarding the networking infrastructure. After approximately an hour with errors, connectivity between services improved significantly without any adjustment on our behalf, and all services started to resume working properly. ### RCA Skills Workflow is highly dependent on several data and networking services from Azure, so any issue with Azure and its service connectivity has a high impact on our service as well. On this occasion, this Azure infrastructure issue had a big impact on our system availability. ### Next steps Our customers rely on Skills Workflow and we understand the impact these incidents have. That's why we are committed to continuously improving our platform. As next steps, we will try to find ways to reduce the impact these kinds of issues have on our system as well as continue to rely on Azure to continually improve their services' reliability. We believe an effort to improve communication with our clients regarding the impact of failures of this nature and the consequent recovery process is needed. A review of the process on this matter is already in progress. This review aims to improve incident response time in a more proactive way, also providing better communication with our customers. --- ## RCA - Mitigated - APIv2 - West Europe - 15-09-2023 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2023-09-15-RCA-Mitigated-APIv2-West-Europe Summary: On 15 September 2023, between 00:43 UTC and 10:05 UTC, approximately, many customers experienced errors or extreme delays accessing the Web Application,… ### Impact summary On 15 September 2023, between 00:43 UTC and 10:05 UTC, approximately, many customers experienced errors or extreme delays accessing the Web Application, APIv2, and other APIs in our West Europe region. Timeout errors and high latency between client applications and the API would occur during a certain amount of time, and several times in the incident timespan. The incident response team quickly noticed that we had multiple errors related mainly to SQL database and service connectivity. During the incident, the Azure Management Portal was not working properly, giving errors when accessing several resources in the West Europe region. Multiple alerts were lost due to this Azure issue. The team engaged Azure Support, and it was confirmed that Azure was investigating a major incident in the West Europe region regarding the networking infrastructure (tracking ID: YKS4-9PZ). This incident started on the 14th September, 23:05 UTC, and impacted several services, including connectivity between services like SQL Databases and App services. As the majority of data on our platform is stored on multiple SQL Databases and we use Azure to rely on the communication between services, this Azure issue had a severe impact on our services. Azure team started rolling out a mitigation just after the problem was acknowledged but service connectivity remained unstable until around 9:00 UTC, when full mitigation occurred. ### RCA Skills Workflow is highly dependent on several data and networking services from Azure, so any issue with Azure and its service connectivity has a high impact in our service as well. On this occasion, this Azure infrastructure issue had a big impact on our system availability. Azure tracked this incident (tracking ID: YKS4-9PZ) and has already provided a full RCA on their side (https://app.azure.com/h/YKS4-9PZ/f8e20a). ### Next steps Our customers rely on Skills Workflow and we understand the impact these incidents have and that's why we are committed to continuously improve our platform. As next steps, we will try to find ways to reduce the impact these kinds of issues have on our system as well as continue to rely on Azure to continually improve their services' reliability. We believe an effort to improve communication with our clients regarding the impact of failures of this nature and the consequent recovery process is needed. A review of the process on this matter is already in progress. Also in progress is a review and improvement of the alerts process. This review aims to improve incident response time in a more proactive way, also providing better communication with our customers. --- ## RCA - Mitigated - APIv2 - West Europe - 21-07-2022 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2022-07-21-RCA-Mitigated-APIv2-West-Europe Summary: On 21 July 2022, between 03:48 UTC and 08:15 UTC, many customers experienced errors or extreme delays accessing the Web Application, APIv2, and other APIs on… ### Impact summary On 21 July 2022, between 03:48 UTC and 08:15 UTC, many customers experienced errors or extreme delays accessing the Web Application, APIv2, and other APIs on our West Europe region. During the peak of the incident, Skills Workflow was practically unusable on the affected region with multiple systems failing. The incident response team quickly noticed that we had multiple errors connecting to SQL Databases from our backend services, in particular the APIv2 service. The team was also unable to access the affected services on the Azure Management Portal, thus posing an added difficulty in diagnosing the situation. This led to the suspicion of a major Azure issue on this data center. At that point the team engaged Azure Support and it was confirmed that Azure was investigating two incidents on the West Europe region; one for SQL Database (tracking ID: 3TBL-PD8) and another for App Service (tracking ID: 3TFH-PZ0). The SQL Database issue was preventing services from connecting to SQL Databases on the affected region, so the team confirmed that this was the cause for the errors connecting to SQL Databases. As the majority of data on our platform is stored on multiple SQL Databases, this Azure issue had a severe impact on our services. As the Azure team started rolling out a mitigation we began to see an improvement on our error rates, and by 8:15 UTC we had no errors, despite the Azure mitigation just being completed by 13:30 UTC. ### RCA Skills Workflow is highly dependant on several data services, being Azure SQL Database our main data store technology, so any issue with this service has a high impact on our services. SQL Database is highly dependable, but, as any service, it can have issues and on this occasion it had an impact on our system availability. Azure is tracking this incident (tracking ID: 3TBL-PD8) and will, eventually, provide a full RCA on their side. ### Next steps Our costumers rely on Skills Workflow and we understand the impact these incidents have and that's why we are committed to continuously improve our platform. As next steps we will try to find ways to reduce the impact these kinds of issues have on our system as well as continue to rely on Azure to continually improve their services' reliability. --- ## RCA - Mitigated - APIv2 - West Europe - 31-01-2023 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2023-01-31-RCA-Mitigated-APIv2-West-Europe Summary: On 31 January 2023, between 08:10 UTC and 08:22 UTC, some customers experienced errors or delays accessing the Web Application or API v2 in our West Europe… ### Impact summary On 31 January 2023, between 08:10 UTC and 08:22 UTC, some customers experienced errors or delays accessing the Web Application or API v2 in our West Europe region. This was during a rollout operation in this region. The process was being monitored, but after some failures, the incident response team identified timeout errors on SQL database calls in the API v2. In total, 3 issues were logged, including one that relates to a bulk operation that may have led to an incomplete transaction. ### RCA Skills Workflow is highly dependent on several data services; Azure SQL Database is our main data store technology, so any issue with this service has a high impact on our services. After further investigation into the problem, it was found that the rollout process contributed to a greater load on the sql Database service, thus resulting in less responsiveness overall. ### Next steps Our customers rely on Skills Workflow and we understand the impact these incidents have, and that's why we are committed to continuously improving our platform. Although there is already a retry policy when connecting to our Azure SQL database, some further actions are needed to assure more stability. We have planned to redefine this retry policy, ensuring that all database dependent operations are resilient to transient errors, including database timeouts and connectivity issues. --- ## RCA - Mitigated - Automations - West Europe - 12-10-2022 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2022-10-12-RCA-Mitigated-Automations-West-Europe Summary: On 12 October 2022, between 08:30 UTC and 09:55 UTC, some customers reported failures on automation execution on our West Europe region. ### Impact summary On 12 October 2022, between 08:30 UTC and 09:55 UTC, some customers reported failures on automation execution on our West Europe region. This was during a rollout operation in this region. The incident response team verified that automations were not executing correctly due to errors when calling the integration API. After some more investigation it was found that some configuration keys were missing in the integration API. The incident team immediately added the missing configuration mitigating the situation. ### RCA In the course of the investigation to the causes of this incident, engineering team identified an issue in the integration API deployment task. A configuration key changed is name between versions. When the integration API rollout started, the new code was pushed to a new slot and the new configuration added to it. In this process, the configuration already in place in production changed as well leading to the incident. This was due to the fact that the new configuration was not bound exclusivelly to the new slot but to every slot. The engineering team changed the way integration API deployment is done. Configuration is now slot specific. Configuration changes only takes place when swapping is done between a staging slot and the production slot. ### Next steps Our costumers rely on Skills Workflow and we understand the impact these incidents have and that's why we are committed to continuously improve our platform. After the changes already made in the integration API deployment task, new measures were put in place to assure services rollout is always followed by the service responsible. The team will also focus in adding more deployment tests and more alerts with value to identify possible failures. --- ## RCA - Mitigated - Blocked Documents - West Europe - 05-04-2023 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2023-04-05-RCA-Mitigated-Blocked-Documents-West-Europe Summary: On April 5, 2023, some customers reported erroneous behavior when accessing documents from our application in our West Europe region. ### Impact summary On April 5, 2023, some customers reported erroneous behavior when accessing documents from our application in our West Europe region. In some documents over which the end user had permissions to read and save, the document would appear blocked without the possibility of unblocking it. The development team investigated this scenario and reported that this was due to a failure or timeout when changing document status in a bulk action. During this operation, documents are blocked because they should not be changed by any other user before the operation finishes. This will preserve document integrity. ### RCA After further investigation into the problem, it was found that during the bulk operation, documents are unblocked as the operation proceeds. If it does not succeed entirely due to an error, documents that have not been processed yet will remain blocked. Due to a tight unblock policy, only the user who blocked the document can unblock it after a certain amount of time. ### Next steps Our customers rely on Skills Workflow and we understand the impact these incidents have, and that's why we are committed to continuously improving our platform. We believe it is important to maintain a block policy over documents that are being changed by a user. This prevents other users from changing the same document at the same time, which could lead to data loss or inconsistency. There is already a ticket created to fix the behavior stated for documents that are not unblocked during a bulk operation or any other routine. The unblock policy will be redefined: even if a document is blocked due to an unexpected behavior or error, it should be unblocked by default after a small period of time and by any user. --- ## RCA - Mitigated - Brazil South - 24-06-2020 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2020-06-24%20RCA-Mitigated-Brazil-South Summary: Between 24 June 2020 18:45 UTC and 24 June 2020 22:50 UTC, some users experienced errors and slow response times on our Brazil South region. ### Impact summary Between 24 June 2020 18:45 UTC and 24 June 2020 22:50 UTC, some users experienced errors and slow response times on our Brazil South region. The team determined that one of Skills Workflow's main services was experiencing connectivity failures accessing the database on Azure SQL. The team opened an urgent support request on Azure Support and worked with the Azure team to solve the issues. The issue was mitigated by performing a service tier upgrade on the affected databases. ### RCA After working with the Azure Support team, the Azure team determined the root cause of this incident as being a series of unrelated events and infrastructure issues that led to multiple database failovers. ## Next steps We understand the impact these issues have on our customers and that's why Skills Workflow is committed to continuously improving our platform. We rely on world-class services provided by Azure, but even those services sometimes fail. Azure is continually improving its platform to prevent issues like these from happening. Skills Workflow will also work to improve our platform resilience by automating mitigation actions when incidents like these happen on Azure services. --- ## RCA - Mitigated - Document Forms - West Europe - 16-04-2026 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2026-04-16-RCA-Mitigated-Document-Forms-West-Europe Summary: On 16 April 2026, after a product installation, some customers experienced issues when opening document creation forms. ### Impact summary On 16 April 2026, after a product installation, some customers experienced issues when opening document creation forms. In affected scenarios, forms were displayed without content and controls were not rendered correctly, preventing users from creating or editing documents as expected. The issue was identified shortly after the deployment by the team during the investigation process. After analysis, it was determined that a configuration parameter had been enabled by default during the installation process. For customers using customized document forms instead of the standard forms, this configuration prevented the forms from being rendered correctly. The issue was corrected promptly after identification by reverting the affected configuration behaviour and validating the impacted scenarios. ### RCA The root cause of the incident was a product installation change that enabled a configuration parameter by default. This parameter was compatible with standard form implementations but introduced compatibility issues in environments using customized document forms. As a result, the application failed to correctly render controls and content in the document creation forms for affected customers. Although the issue was quickly identified and mitigated by the team, the incident exposed a gap in the validation process for non-standard customer configurations and usability scenarios. ### Next steps Our customers rely on document workflows being consistently available and functional, and we recognize the impact this incident had on affected operations. As next steps, we will reinforce the QA validation process with a more proactive approach focused on configuration-sensitive changes. Additional usability and regression tests will also be introduced for critical workflows, especially for customers using customized forms and non-standard implementations. We are also reviewing deployment validation procedures to ensure configuration defaults are properly assessed against different customer scenarios before release. --- ## RCA - Mitigated - E-Mail Notifications - All Regions - 13-05-2019 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2019-05-13-RCA-Mitigated-E-Mail-Notifications-All-Regions Summary: Between 13 May 2019 and 14 May 2019, some users failed to receive a notification via e-mail across all regions. ### Impact summary Between 13 May 2019 and 14 May 2019, some users failed to receive a notification via e-mail across all regions. Upon receiving reports from our users regarding this issue our engineers identified the issue as a send quota exhausted on one of our providers and applied mitigation. ### RCA One of our e-mail providers hit a send quota limit without firing any of the alerts in place to allow us to manage the quotas before they are hit. We found that recent maintenance on the alerts set an invalid alert configuration that went undetected. ### Next steps We understand the impact these issues have on our customers and that's why Skills Workflow is committed to continuously improving our platform. The alerts have been fixed and a new process for changing the alerts has been deployed to avoid invalid configurations. --- ## RCA - Mitigated - East US - 06-07-2020 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2020-07-06-RCA-Mitigated-East-US Summary: Starting 6 July 2020 19:22 UTC and 16 July 2020 17:22 UTC, some users intermittently experienced degraded overall system response in our East US region. ### Impact summary Starting 6 July 2020 19:22 UTC and 16 July 2020 17:22 UTC, some users intermittently experienced degraded overall system response in our East US region. The team determined that on peak times when multiple user requests were being handled system performance degraded. These performance peaks would happen multiple times during the day and would not last more than 30 minutes. After an investigation where the team analyzed multiple telemetry sources and profile traces, the team determined that the main service was missing a configuration that prevented lock contention under high load. ### RCA This incident was due to contention on a lock accessing the database on the main system service when the system is under high system load. The configuration that prevents this contention was already rolled out to one region, but it failed to be applied to the East US and the remaining regions. Said configuration was not applied because of two reasons: 1. It's rollout was not automated 2. It was not set as the new default configuration. ### Next steps We understand the impact these issues have on our customers and that's why Skills Workflow is committed to continuously improving our platform. The team has since rolled out this configuration to all regions. A process was put into place in order to automate these configuration rollouts and to ensure that the team updates the default configuration whenever issues like these occur. --- ## RCA - Mitigated - East US - 10-07-2020 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2020-07-10-RCA-Mitigated-EastUS Summary: Starting 6 July 2020 19:22 UTC and 16 July 2020 17:22 UTC, some users intermittently experienced degraded overall system response in our East US region. ### Impact summary Starting 6 July 2020 19:22 UTC and 16 July 2020 17:22 UTC, some users intermittently experienced degraded overall system response in our East US region. The team determined that on peak times when multiple user requests were being handled system performance degraded. These performance peaks would happen multiple times during the day and would not last more than 30 minutes. After an investigation where the team analyzed multiple telemetry sources and profile traces, the team determined that the main service was missing a configuration that prevented lock contention under high load. ### RCA This incident was due to contention on a lock accessing the database on the main system service when the system is under high system load. The configuration that prevents this contention was already rolled out to one region, but it failed to be applied to the East US and the remaining regions. Said configuration was not applied because of two reasons: 1. It's rollout was not automated 2. It was not set as the new default configuration. ### Next steps We understand the impact these issues have on our customers and that's why Skills Workflow is committed to continuously improving our platform. The team has since rolled out this configuration to all regions. A process was put into place in order to automate these configuration rollouts and to ensure that the team updates the default configuration whenever issues like these occur. --- ## RCA - Mitigated - Production Outage East US - 11-05-2026 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2026-05-11-RCA-Mitigated-Production-Outage-East-US Summary: ---------------------------------------------------------------- ---------------------------------------------------------------- ### Impact summary On 11 May 2026, the production environment hosted in the East US (EUS) region became inaccessible for all tenants until approximately 15:30 UTC. During the incident, several services hosted in Microsoft Azure stopped responding, resulting in a complete service outage for affected customers. The operations team was immediately engaged and started investigating the issue. Initial troubleshooting efforts were hampered by the fact that the affected Azure services could not be restarted successfully through the Azure Management Portal. As service recovery through standard procedures was not possible, a workaround was implemented by recreating the affected services in a new Azure Kubernetes Service (AKS) cluster. Following this recovery action, service availability was restored and all tenants regained access to the platform. ### RCA The incident was caused by an issue within the Microsoft Azure infrastructure. Following an investigation conducted by Microsoft, the root cause was identified as a bug in the underlying Azure Kubernetes Service (AKS) node provisioning process. The issue caused platform upgrades to enter a failure loop because newly created virtual machine instances were unable to register successfully with the node pool. As a consequence, the affected AKS environment became stuck in an activation state, preventing services from operating normally and making standard recovery actions ineffective. To restore service, the affected workloads were migrated to a newly created AKS environment. Microsoft subsequently developed and deployed a fix for the underlying issue. ### Next steps Our customers rely on the continuous availability of the platform, and we understand the impact this incident had on their operations. As next steps, we will continue to review and improve our disaster recovery and infrastructure recovery procedures to reduce service restoration times in situations where cloud provider infrastructure issues occur. We will also continue to work closely with Microsoft Azure to monitor platform reliability and ensure that corrective actions implemented by their engineering teams are effective in preventing similar incidents. Additionally, we are reviewing opportunities to further automate recovery procedures and improve operational visibility during infrastructure-related incidents, allowing faster diagnosis and mitigation when external platform failures occur. --- ## RCA - Mitigated - Proofing Automations - West Europe - 06-06-2022 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2022-06-06-RCA-Mitigated-Proofing-Automations-West-Europe Summary: Between 23 March 16:28 UTC and 31 March 15:29, users reported some tasks getting stuck at the “Proof ID Generated” stage despite of already having Proofs… ### Impact summary Between 23 March 16:28 UTC and 31 March 15:29, users reported some tasks getting stuck at the "Proof ID Generated" stage despite of already having Proofs created. After conducting an investigation, the team figured there was a misconfiguration in the automation responsible for generating Proof IDs and Creating new Proofs at the task level. The cases where the issue was reported where manually dealt by the team. Later on, the fix was applied, tested and put in Production to mitigate possible future cases. ### RCA Whenever a Proof is created, 2 automations run on the background: one to generate a proof ID and another to create the proof. The team concluded that the automation which indicates the "ID was generated" was taking longer than the automation which indicates that the "Proof was created" (The time taken between these two events is about fraction of seconds and only occurs occasionally) In summary, proofs were being created without an ID and the task was being kept at the "Proof ID generation" stage because the proof was already created. To correct the issue, the team created a dependency so that the second automation (Proof creation) would only start running after the first one (Proof ID generation) was finished. ### Next Steps We understand the impact these issues have on our customers and that's why Skills Workflow is committed to continuously improving our platform. Besides from fixing the bug that lead to this incident, we are on the lookout and ready to action in case this incident reoccurs. --- ## RCA - Mitigated - Search - Intermittent Errors - All Regions - 28-02-2022 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2022-02-28-RCA-Mitigated-Search-Intermittent-Errors-All-Regions Summary: Between 28 February 2022 0:00 UTC and 3 March 2022 12:00 UTC, some users experienced intermittent errors while using the search feature. ### Impact summary Between 28 February 2022 0:00 UTC and 3 March 2022 12:00 UTC, some users experienced intermittent errors while using the search feature. While investigating, the team determined that the errors were "502 Bad Gateway" and happened intermittently on all regions. After ruling out several components, the team determined that the issue was caused by a large amount of diagnostics data being included on the service response. The team mitigated this issue by disabling diagnostics data on the search service. ### RCA The search feature includes the possibility of returning diagnostics data to help debug issues such as documents not showing up to the user, etc. This information was returned on HTTP response headers. On certain situations this data was very large (more than 8KB), and the Azure Load Balancer would drop the connection and issue a 502 Bad Gateway response to the client due to exceeding the maximum header size, leading to the error experienced by the affected users. After determining the issue, the team changed the way diagnostics data is returned to the client to avoid header size issues with the Azure Load Balancer. ### Next steps We understand the impact these issues have on our customers and that's why Skills Workflow is committed to continuously improving our platform. --- ## RCA - Mitigated - SSO - Multiple Regions - 30-06-2021 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2021-06-30-RCA-Mitigated-SSO-Multiple-Regions Summary: Starting 30 June 2021 - 14:16 UTC until 1 July 10:00 UTC, some users intermittently experienced errors using Single Sign On authentication (SSO) on our Brazil… ### Impact summary Starting 30 June 2021 - 14:16 UTC until 1 July 10:00 UTC, some users intermittently experienced errors using Single Sign On authentication (SSO) on our Brazil South, Southeast Asia and East US regions. Some users had to attempt the operation multiple times until it succeeded. Upon investigation, the team found that data protection keys used in the SSO process were out of sync across worker nodes on the affected regions. Users that ended the SSO process on a different node than the one it started on would get an error as the nodes were using different keys. The team quickly routed all SSO traffic to the healthy region (West Europe) and by 10:00 UTC the West Europe datacenter was handling all SSO traffic without any issues. After confirming that all SSO traffic was being handled successfully on the healthy region the team forced a key sync on each affected region by manually restarting the front end services. By 10:29 UTC, the team determined that the affected regions were healthy and started to slowly move SSO traffic to those regions while actively monitoring their behaviour. At 11:30 UTC SSO traffic routing was restored to the usual configuration so users would hit the closest datacenter, as usual, for reduced latency. ### RCA While investigating this incident, the team engaged the Azure App Services Support team and Product Group to help determine why the keys became out of sync across nodes on the same server farm. The Azure team confirmed that a platform update on the affected regions triggered this issue. Worker nodes on the server farm use a shared storage to store all service data (code, keys, temporary data, etc). For performance and resilience reasons the SSO service is configured to locally cache the shared data. The above mentioned Azure platform update triggered new keys to be generated, but it didn't restart the nodes in order to sync the keys. ### Next steps We understand the impact these issues have on our customers and that's why Skills Workflow is committed to continuously improve our platform. The SSO team will change the way data protection keys are stored to avoid this type of issue and not rely on the platform to force the nodes to sync the keys. Service monitoring was improved to better detect and alert when the error frequency is low. --- ## RCA - Mitigated - Templates - West Europe - 20-07-2022 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2022-07-20-RCA-Mitigated-Templates-West-Europe Summary: On 20 July 2022, between 09:30 UTC and 11:30 UTC, several users reported that when creating Jobs, some actions responsible for task creation based in… ### Impact summary On 20 July 2022, between 09:30 UTC and 11:30 UTC, several users reported that when creating Jobs, some actions responsible for task creation based in templates were not working. Upon investigation it was verified that Template service configuration was changed during a deployment process. This change led to the service not responding correctly to requests from production environments because it was configured to work with test environments only. A corrective patch was deployed with the mitigation and it was verified by the incident response team that task creation actions started to work properly. ### RCA After the corrective patch deployment, development team has updated the required steps needed in code reviewing, changing the number of reviewers to include one more person, and enforcing service responsibles as mandatory. ### Next steps Our costumers rely on Skills Workflow and we understand the impact these incidents have and that's why we are committed to continuously improve our platform. As next steps we will try to find ways to reduce the impact these kinds of issues have on our system, this will include an evaluation of our current deployment lifecycle and redefining new testing functions over Skills Workflow. --- ## RCA - Mitigated - V1 - West Europe - 20-08-2018 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2019-08-20-RCA-Mitigated-V1-West-Europe Summary: Starting at around 20-08-2018 2:03 UTC until 7:40 UTC a small subset or users using Skills Workflow V1 hosted on the West Europe region may have experienced… ### Impact summary Starting at around 20-08-2018 2:03 UTC until 7:40 UTC a small subset or users using Skills Workflow V1 hosted on the West Europe region may have experienced errors logging in. About 1% of all requests were affected. All affected requests were served by the same server on our West Europe V1 server farm. The DevOps team mitigated the issue by forcing an application restart on the affected server. ### RCA The affected node could not correctly read a configuration file stored on disk thus causing the requests that needed to read the file to fail. The DevOps team tried to mitigate the issue by issuing "soft" restarts of the service with only partial success. The issue was fully mitigated after applying a "hard" restart to the service. Failure to read the configuration file was caused by a race condition in certain node restart situations. ### Next steps The team will roll out a fix to prevent the said race condition from happening. We are deeply sorry for any inconvenience this issue might have caused. We understand the impact these issues have on our customers and our team will be making improvements to our system in order to prevent future issues. --- ## RCA - Mitigated - V2 - Brazil South - 26-07-2018 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2018-07-26-RCA-Mitigated-V2-Brazil-South Summary: Starting on 26-07-2018 15:15 UTC and until 26-07-2018 15:50 UTC, some users experienced errors trying to access Skills Workflow V2 on the Brazil South region. ### Impact summary Starting on 26-07-2018 15:15 UTC and until 26-07-2018 15:50 UTC, some users experienced errors trying to access Skills Workflow V2 on the Brazil South region. The issue was detected and mitigated by the team by applying a parameter change on a backend service. ### RCA During a routine upgrade to a backend service, a service parameter was wrongly changed by the automated upgrade process causing the service to have errors accessing another backend service. The DevOps team mitigated the issue by manually setting the parameter to its correct value. The automated process was fixed to correctly update the parameter value. ### Next steps We are deeply sorry for any inconvenience this issue might have caused. We understand the impact these issues have on our customers and our team will be making improvements to our system in order to prevent future issues. --- ## RCA - Mitigated - Views - West Europe - 20-07-2022 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2022-07-20-RCA-Mitigated-Views-West-Europe Summary: On 20 July 2022, between 08:50 UTC and 09:30 UTC, several users reported issues when logging on with Single Sign-On or accessing different pages in Skills… ### Impact summary On 20 July 2022, between 08:50 UTC and 09:30 UTC, several users reported issues when logging on with Single Sign-On or accessing different pages in Skills Workflow. Upon investigation it was verified that the deployment of a Custom Views service was originating errors in our backend. The incident response team decided to revert this service rollout to the previous version. This action mitigated this issue. ### RCA After some investigation, engineering team discovered that the service rollout had originated an API breaking change. Due to this fact every endpoint with communication with the Custom Views service would fail to respond successfully. Service was refactored and fixed to work with older versions of the API. Our team has already rolled out this version. Service deployment was changed including the required steps needed for code reviewing, changing the number of reviewers to include one more person, and enforcing service responsibles as mandatory. ### Next steps Our costumers rely on Skills Workflow and we understand the impact these incidents have and that's why we are committed to continuously improve our platform. As next steps we will try to find ways to reduce the impact these kinds of issues have on our system, this will include an evaluation of our current deployment lifecycle and redefining new testing functions over Skills Workflow. --- ## RCA - Mitigated - Webhooks - Not Firing - West Europe - 06-06-2022 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2022-06-07-RCA-Mitigated-Webhooks-Not-Firing-West-Europe Summary: On 6 June 2022, between 14:57 UTC and 18:48 UTC, webhooks were not invoked in response to system events. ### Impact summary On 6 June 2022, between 14:57 UTC and 18:48 UTC, webhooks were not invoked in response to system events. That meant that any downstream actions that responded to webhooks were not executed during the impact period. Upon investigation, the incident reponse team determined that an Azure Function responsible for responding to system events and evaluating Webhook subscriptions was not consuming messages from its queue and showed no activity. After trying to manually restart the Azure Function, using several different approaches, without success and running all Azure Diagnostics on the function, the team provisioned a new function infrastructure and deployed the function code, mitigating the issue. The new function instance quickly processed all pending event messages; by 18:48 UTC all pending webhooks were invoked and no work was lost. ### RCA The Webhooks system on Skills Workflow uses an Azure Function whose responsibility is to determine for each event which webhooks are relevant and invoke them through HTTP REST calls. This function consumes event messages from the event queue to do its processing and during the impact period it completely stopped consuming messages. Azure Functions are a serverless way (FaaS) to run code in the cloud in a way that's fully managed by Azure and that scales almost indefinitely. The code for these serverles functions is stored on storage accounts as there is no concept of server. The team involved Azure Support to help identify what caused the Azure Function to stop working. Azure Support determined that the function stopped due to its number of worker hosts being dropped down to zero in response to a restart and then not starting properly. This behavior was caused by an open issue on Azure Functions runtime when multiple functions share the same storage account. This issue causes the function to be restarted and may prevent the function from starting correctly due to not being able to access the storage account. As we use a shared storage account per region for all our functions in the same region, we were affected by this issue. ### Next steps As next steps the following actions will be taken: - Redeploy all Azure Functions with separate storage accounts for added stability and performance as per Azure Support recommendation - Optimize this Azure Function to perform better under high loads - Design architectural changes to allow for automatic failover or recovery of unhealthy functions We understand the impact these incidents have on our customers and that's why Skills Workflow is committed to continuously improving our platform. --- ## RCA - Mitigated - Webhooks - West Europe - 12-02-2021 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2021-02-12-RCA-Mitigated-Webhooks-West-Europe Summary: Between 28 February 2022 0:00 UTC and 3 March 2022 12:00 UTC, some users experienced intermittent errors while using the search feature. ## Impact summary Between 28 February 2022 0:00 UTC and 3 March 2022 12:00 UTC, some users experienced intermittent errors while using the search feature. While investigating, the team determined that the errors were "502 Bad Gateway" and happened intermittently on all regions. After ruling out several components, the team determined that the issue was caused by a large amount of diagnostics data being included on the service response. The team mitigated this issue by disabling diagnostics data on the search service. ### RCA The search feature includes the possibility of returning diagnostics data to help debug issues such as documents not showing up to the user, etc. This information was returned on HTTP response headers. On certain situations this data was very large (more than 8KB), and the Azure Load Balancer would drop the connection and issue a 502 Bad Gateway response to the client due to exceeding the maximum header size, leading to the error experienced by the affected users. After determining the issue, the team changed the way diagnostics data is returned to the client to avoid header size issues with the Azure Load Balancer. ### Next steps We understand the impact these issues have on our customers and that's why Skills Workflow is committed to continuously improving our platform. --- ## RCA - Mitigated - Webhooks and Automation - West Europe - 23-07-2021 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2021-07-23-RCA-Mitigated-Webhooks-and-Automation-West-Europe Summary: Starting 23 July 2021 - 09:56 UTC until 16:25 UTC, customers have experienced failures on webhook and automation execution on our West Europe region. ### Impact summary Starting 23 July 2021 - 09:56 UTC until 16:25 UTC, customers have experienced failures on webhook and automation execution on our West Europe region. Impact was mainly felt by customers with automations triggered by webhooks. During this period some automations were not executed. Upon investigation, the team found that the backend queue responsible for broadcasting events had reached it's maximum size limit. This caused that all incoming event messages were refused during the affected period thus leading to the webhook service -- which relies on internal events -- not executing. At 16:20 UTC the backend service was restored successfully. At 16:25 UTC the team determined that all affected services were healthy and automations were being triggered correctly. ### RCA After investigation, the team determined that a service that subscribes from event message queue started to fail. All messages that caused the service to error were then piled in an internal dead lettering queue. This queue is part of the queue service itself. This behavior led to the queue service reaching its maximum size limit quota after some time. This led to all new event messages being refused which then caused downstream subscribers -- webhook service -- to not receive events. No alarms were triggered for this incident due to several reasons. No errors were logged during the impact period. An alert should have been triggered in the backend service that was consuming messages but due to administrative changes in resources in Azure the alert was left in an invalid state without any warning. After determining the issue, the team quickly mitigated the problem increasing the queue service maximum size quota and draining the dead letter queue. ### Next steps We understand the impact these issues have on our customers and that's why Skills Workflow is committed to continuously improving our platform. The team has improved the queue monitoring creating new alarms for the maximum size quota. Affected consumer service alarm was fixed. This alarm fires on an unexpected error ratio. Broadcasting dead lettering queue process will be reviewed to prevent future incidents. This review will focus on management rules and automatic cleanup after a certain amount of time. Event consumption process will be reviewed. It will be discussed to have a dead letter approach over the event processing to allow replaying lost events. The team will also focus on finding ways to test alerting and overall system resilience like injecting failures, simulating failures, etc. --- ## RCA - Mitigated - Webhooks, User Errors - West Europe - 24-09-2021 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2021-09-24-RCA-Mitigated-Webhooks-User-Errors-West-Europe Summary: Between 24 September 2021 - 12:29 UTC and 12:55 UTC, a very small subset of customers have experienced failures and extremely high latency on webhook and… ### Impact summary Between 24 September 2021 - 12:29 UTC and 12:55 UTC, a very small subset of customers have experienced failures and extremely high latency on webhook and automation execution as well as intermittent errors logging in and saving documents on our West Europe region. Upon investigation, the team found that the backend service responsible for storing internal events for distribution across all system services had reached an operational limit on one of its partitions due to extremely high number of events (actually, several millions). Due to this fact some events were not saved -- thus the intermittent errors -- and event distribution began taking a long time due to the extremely high number of events to process, leading to high latency firing webhooks and executing automations. At 12:55 UTC the team mitigated this issue by reducing the event time to live on the initial storage. ### RCA After investigating all the telemetry and logs leading to the incident and reviewing code on the core API, the team determined that a bug on the high performance code responsible for writing events to the event store was responsible for exponentially generating the same events. This was mainly triggered by bulk operations. After determining the issue, the team rolled out a fix for the event writing code on the core API. ### Next steps We understand the impact these issues have on our customers and that's why Skills Workflow is committed to continuously improving our platform. Besides from fixing the bug that lead to this incident, the team is also working on changing the event partitioning strategy to ensure better performance and scalability in the presence of extremely high number of events. --- ## RCA - Mitigated V2 – West Europe - 02-07-2018 URL: https://documentation.skillsworkflow.com/docs/trust/operational%20continuity%20%26%20incident%20response/availability%20incidents/2018-07-02-RCA-Mitigated-V2%E2%80%93West-Europe Summary: Starting on 02-07-2018 01:45:43 UTC some users had errors trying to access Skills Workflow V2 on tenants hosted on the West Europe data center This issue is… ### Preliminary analysis Starting on 02-07-2018 01:45:43 UTC some users had errors trying to access Skills Workflow V2 on tenants hosted on the West Europe data center - About 3% of total requests to the application were affected by this issue - The outage was due to an intermittent connectivity issue between a backend API and the Azure SQL Database - Because of the intermittent nature of the issue, our availability probes failed to detect the outage - Our engineers are actively working with Azure support to find the cause for the connectivity problems. ### Update (11-07-2018) - Our team is analysing all available telemetry and working with Azure support to establish a full Root Cause - Our DevOps team will improve our issue detection system to employ different probes and error telemetry to detect these kinds of issues early - Critical backend services will be improved in order to be more resilient to database connectivity problems. #### Update (11-07-2018) This issue is not fully mitigated. We still observed a recurrence today from 5:05 UTC to 6:35 UTC with an impact on about 3% of customer requests. At this point we have performed the following actions: - Our team improved our telemetry and probes and now we can effectively detect this kind of issue early - Microsoft's Azure SQL Database Support team determined that the connectivity issues were due to database reconfiguration (cluster reconfiguration, node migration, etc.). These reconfiguration operations are normal on cloud environments and can happen occasionally, but should not take more than 60 seconds - Microsoft's Azure SQL Database Support team is trying to determine why the reconfiguration is taking much more than 60 seconds - In the meantime, to mitigate further the issue while we wait for Microsoft to solve the issue, we are rolling out an update to our backend services to improve their resiliency to transient errors and to improve database connection recovery. #### Update (19-07-2018) - We will keep working with the Azure SQL Database team to determine what is causing the reconfigurations to take a long time - Our DevOps team will keep monitoring the system health to assess the effectiveness of the mitigations we are rolling out; Azure SQL Database product team informed that the Root Cause, though not fully established, is related to the in-memory OLTP SQL Feature. Based on this feedback, we applied an additional mitigation by disabling the use of in-memory OLTP database features until the full RCA is determined and the Azure SQL Database product team applies a fix for the issue. #### Next steps - We will keep working with the Azure SQL Database product team to establish the full Root Cause and to apply a fix - Our DevOps team will keep monitoring the system health to assess the effectiveness of the mitigations we are rolled out; ### RCA Azure SQL Database product team at Microsoft established the root cause to be a silent failure of the internal SQL compiler and linker of the in-memory SQL Feature causing the long delay during database reconfiguration. Based on this feedback our team fully disabled usage of in-memory OLTP feature. We are deeply sorry for any inconvenience this issue might have caused. We understand the impact these issues have on our customers and we will be making improvements to our system in order to prevent future issues. --- ## Recording a browser performance profile URL: https://documentation.skillsworkflow.com/docs/trust/service%20quality%20%26%20change%20management/measuring-performance Summary: How to record a Chrome performance profile of Skills Workflow and send it to the support team. To measure the performance of your Google Chrome browser using Skills Workflow you must: - Open Chrome in your Skills Workflow login page - Perform the steps below - Save the profile - Send us the profile saved ### Please follow the steps below to record your profile - Open your Chrome in your Skills Workflow login page, and do a right click to open "Inspect" - Once the "Inspect menu" is open, please click on the "Performance" tab Start by clicking on the record button, then refresh the page and login as is normally done 4. Browse the pages where you know of possible issues of slowness. We recommend that you browse the pages where you usually work so that we can analyze according to your working method. 6. Send us the profile saved, and our team will evaluate it. --- ## Security URL: https://documentation.skillsworkflow.com/docs/trust/security Summary: At Skills Workflow, we take the security, privacy and reliability of our platform seriously. ## Our Commitment to Security At Skills Workflow, we take the security, privacy and reliability of our platform seriously. Our mission is to help teams work better together, and that includes protecting their data at every level. This page outlines the measures we take to ensure your information is safe, our systems are resilient and our compliance standards are up to date. --- ## Security Ratings We’re proud of our performance in independent third-party security assessments: --- ## Certifications We follow industry best practices and standards to ensure your data is handled securely: - SOC - GDPR compliance --- ## Data Protection & Privacy We apply strong safeguards to protect all personal and business-critical data. - **Encryption:** All data is encrypted in transit using TLS 1.2+ and at rest with AES-256. - **Data Residency:** All data is hosted in secure, enterprise-grade data centers within [European Union / United States]. - **Privacy:** We comply with GDPR and offer full access, portability and deletion tools to users. [View our Privacy Policy](https://www.skillsworkflow.com/privacy-policy) --- ## Infrastructure & Availability We use modern cloud infrastructure and robust operational practices to maintain system availability and integrity. - Hosted on Microsoft Azure - High availability with auto-scaling, load balancing and data redundancy - Daily backups and disaster recovery plan - 24/7 monitoring and alerting [Check live uptime status](index.md) --- ## Access Controls & Authentication Security starts with access management and identity control. - Role-Based Access Control (RBAC) - Single Sign-On (SSO) supported - Strict internal security policies for system access - Session expiration and protection against XSS, CSRF and brute-force attacks --- ## Responsible Disclosure We appreciate contributions from the security community. If you believe you have found a vulnerability, please report it responsibly. - Email: [security@skillsworkflow.com](mailto:security@skillsworkflow.com) - We investigate all reports promptly --- ## Contact For any security-related questions, incidents or concerns, please contact our team at: **[security@skillsworkflow.com](mailto:security@skillsworkflow.com)** --- ## Support Model & SLA URL: https://documentation.skillsworkflow.com/docs/trust/service%20quality%20%26%20change%20management/support-model-sla Summary: SKILLS0018OP039 Explains the ticketing system, service level agreements, and escalation models for issue resolution. SKILLS0018OP039 ## Overview Explains the ticketing system, service level agreements, and escalation models for issue resolution. ## Key Topics ### Ticketing and SLAs Defines priority levels P1–P5 with response and resolution times. ### Workflow Management Covers workflows for different ticket types from questions to enhancement requests. ### Communication and Escalation Outlines communication processes and escalation paths. ## Document Preview --- ## Trust URL: https://documentation.skillsworkflow.com/docs/trust Summary: Availability, security, privacy and incident information for customers, IT teams and procurement. Welcome to the **Skills Workflow Trust Page**. We’re committed to transparency and reliability. This page provides real-time updates on the availability of our systems, scheduled maintenance, and any incidents that might impact your experience. ## Live Service Status The panel below shows the current operational status of our systems, including platform uptime, API availability, integrations and infrastructure. - You can also view the full page directly at: [https://status.skillsworkflow.com](https://status.skillsworkflow.com) ## Maintenance & Incident Updates All scheduled maintenance windows and incident updates are posted here. If an issue arises, our team will update the status board in real time and provide estimated resolution timelines. We aim to minimize disruptions and communicate clearly when any part of the platform is affected. ## Experiencing Issues? If something seems off and it’s not reflected above, please let us know. - **Submit a request via the Help Desk:** [helpdesk.skillsworkflow.com](https://helpdesk.skillsworkflow.com) - **Email our support team:** [support@skillsworkflow.com](mailto:support@skillsworkflow.com) We're here to help. ## Trust & Security Want to learn more about how we protect your data and ensure platform reliability? Check our [Security & Trust page](/docs/trust/security) ------------------------- *Thank you for trusting Skills Workflow. We’ll always do our best to keep things running smoothly.* # Administration --- ## Assigning Absence Types URL: https://documentation.skillsworkflow.com/docs/administration/calendars/absence-types Summary: Follow the steps below to massively assign absence types. Navigate to "Maintenance" and select the "Users" module. - In the list of users in the column to the left of "Name," select the users (limited to 25 users at a time)​ - Click on the three dots to the right of the search bar.​ - In the menu, choose "Assign Absence Types" After completing the previous procedure, a pop-up for assigning absences will open. - In the pop-up, choose "Assign Absence Types"​ - Select the absence to be inserted - Verify the dates and year - Click the Apply button - Click OK to Save :::note To delete the assignment, it's in the absence assignment pop-up, selecting the Delete option. ::: --- ## Clients URL: https://documentation.skillsworkflow.com/docs/administration/importing-data/clients Summary: Importing client records into Skills Workflow. client --- ## Create Leave Types URL: https://documentation.skillsworkflow.com/docs/administration/calendars/leave-types Summary: Several leave types can be created in a company, such as: Follow the steps below to create a new leave type: 3. A popup will show a form to be filled in and to create the desired Leave Type. 4. After filling in all the information, click “OK” to save. Each leave type might require additional specific configurations. - Company: It is important to fill in this information, specially in environments shared with other Group Companies. Select your company name in this field. - Total Leave Days: Numerically enter the number of days equivalent to this leave type. Example: If users are entitled to a anniversary leave day, add the value “1” in this field. - Expiration Date: Final date where users are allowed to book days for this leave type. - Allow Half Days: Option to be checked if particular leave types allows users to book half days. - Allow Weekend Selection: Option to be checked if particular leave type allows users to book leaves on weekends, for example, Maternity Leave. - Allow Holiday Selection: Option to be check if particular leave type allows users to book leaves on holidays. - Accountable in Timesheets: Option checked by default. It shows this particular leave type in timesheets scheduler. - HR Approval Only: Requires Human Resources approval. - Leave in Hours: Option to add leaves in hours instead of full/half day, for exemple, Medical Leave. - Requires Attachments: It’s mandatory to add attachments, for example, medical certificate. --- ## Create Typologies URL: https://documentation.skillsworkflow.com/docs/administration/typologies Summary: As every person has his specific role inside the company, every user registered in Skills has his position linked to a specific “typology”. As every person has his specific role inside the company, every user registered in Skills has his position linked to a specific "typology". To create a typology, navigate to Maintenance and locate the "Typologies" option Click on the "+" icon located in the upper right corner of the screen. Fill the mandatory fields registered in red." --- ## Create User URL: https://documentation.skillsworkflow.com/docs/administration/users/create-a-user Summary: Navigate to Maintenance and enter the “User” module To create a new user there are two ways Navigate to Maintenance and enter the "User" module To create a new user there are two ways ### Create Create a user and fill in all required fields (they are marked with a red dot) and follow all the steps below ### Duplicate Duplicate an existing user Select an active user already registered from the same department and position of this new user you want to create Go to the upper right corner of the screen and click on the three dots. A menu will open and in it select DUPLICATE USER. On the screen for duplicating users, put the name and surname of the new user to be registered and the user data (name.surname) at the end, click on DUPLICATE. Try looking at users created to follow the uppercase and lowercase letter pattern The new user is created. The screen will open with his data. Make the necessary adjustments, and click the Diskette icon to Save. --- ## Custom Style URL: https://documentation.skillsworkflow.com/docs/administration/system/custom-style Summary: On this page you will find the process of how to customize the style of the document. ### Description On this page you will find the process of how to customize the style of the document. To activate one or more properties of the the Custom Style, the Use Custom button should be enabled Properties Type Required Description Use Custom Boolean false Set the custom style of the icon Main Color String false Change the color of the document Secondary Color String false Change the color of the icon Icon String false Change the icon of the document Plural Name String false Change the name of the document in the menu Singular Name String false Change the name of the document's tooltip ## Example --- ## Custom Tables URL: https://documentation.skillsworkflow.com/docs/administration/custom-tables Summary: Custom Tables allow you to extend the Skills Workflow data model by creating your own tables with custom columns and data types. ## Overview Custom Tables allow you to extend the Skills Workflow data model by creating your own tables with custom columns and data types. They are ideal for storing additional structured data that does not fit into standard document fields — for example, product catalogs, specification mappings, or lookup tables. Custom tables support: - **Custom schema** — define your own columns with specific data types - **Role-based permissions** — control who can read and who can write - **Full CRUD** — create, read, update, and delete via the UI, SDK, or API - **Query integration** — read data using SQL queries with the `CustomTable` namespace - **Import / Export** — bulk data management via JSON files --- ## Navigating to Custom Tables 1. Go to **Maintenance** in the main menu 2. Select the **Custom Tables** module You will see a list of all existing custom tables in the system. --- ## Creating a Custom Table To create a new custom table: 1. Click the **+** button in the Custom Tables list 2. Enter the **Table Name** (must be unique, no spaces — use PascalCase, e.g. `ProductCatalog`) 3. Define the **Key Column** — typically `Oid` with data type `UniqueIdentifier` (GUID) 4. Add **Columns** with their names and data types Column names should use PascalCase (e.g. `ProductName`, `IsActive`). Once a column is created, its data type cannot be changed — only new columns can be added. --- ## Managing Permissions Each custom table has two permission roles: - **Read Role** — determines which users can read data from the table - **Save Role** — determines which users can insert, update, or delete data To configure permissions: 1. Select a custom table from the list 2. In the **Permissions** panel, set the **Read Role** and **Save Role** 3. Click **Save** --- ## Viewing Data After selecting a custom table, the data grid displays all stored rows with their column values. The grid shows: - The **key column** (e.g. Oid) - All custom columns and their current values - A **row count** at the bottom --- ## Reading Data via Queries To read custom table data using SQL queries: 1. Navigate to **Maintenance → Queries** 2. Create or edit a query 3. Set the **Namespace** to `CustomTable` 4. Write your SQL referencing the table as `[customtables].[YourTableName]` **Example:** ```sql SELECT Oid, Name, Price, IsActive FROM [customtables].[ProductCatalog] WHERE IsActive = 1 ORDER BY Name ``` The `CustomTable` namespace is required for the query engine to resolve custom table references at runtime. Without it, the query will not find your tables. --- ## SDK Reference Use the SDK methods below to interact with custom tables programmatically from workspaces, automations, or any JavaScript context inside Skills Workflow. **Namespace:** `SW.Document.CustomTable` View SDK Methods --- ## API Reference For external integrations or direct HTTP calls, use the REST API endpoints below. View API Endpoints --- ## Departments URL: https://documentation.skillsworkflow.com/docs/administration/importing-data/departments Summary: In this article, we will guide you through the simple steps necessary to efficiently import departments, ensuring a smooth integration process. In this article, we will guide you through the simple steps necessary to efficiently import departments, ensuring a smooth integration process. The department import process will: - Create the department - Associate it with the company, division configured in the import file To successfully import the data, make sure there are no duplicate entries in the system. The following combination must be unique: - Name | Active | Company | Division | Department Type| ::: Preparing your data file: - Format the department file correctly for a smooth import. - Ensure that the data is organized and structured in a compatible format. - Verify that all mandatory fields are included and filled in correctly. - Consider any specific data formatting guidelines or restrictions mentioned in the system documentation. - Carefully check for the existence of inconsistencies or errors in the data to avoid issues during the import process. --- ## Description Templates URL: https://documentation.skillsworkflow.com/docs/administration/description-templates Summary: Go to “Maintenance” and click on the module “Template Description” A screen for creating the Briefing will open. Go to "Maintenance" and click on the module "Template Description" A screen for creating the Briefing will open. You must give a name/title to this document It is necessary to choose which type of document will receive this template In the free field you can create the document and format it as you wish. To save click OK After creating the Briefing, it is necessary to link it to the Department that will use it and to the Activity Types. Go to Maintenance and look for the "types" module You can create a type or you can associate it with an already created type by choosing in the "Description Template" field --- ## Edit Profile URL: https://documentation.skillsworkflow.com/docs/administration/users/edit-a-profile Summary: On the Skill Workflow Home page, at the top of the page you will see your name. On the Skill Workflow Home page, at the top of the page you will see your name. When you click on your name you will have the option to edit your profile A screen will open with your previously registered profile. On this screen, you can insert your photo and fill in/change your data, as well as modify the notifications you want to receive in your Skills Workflow. By default, the system flags the first five notifications that allow you to receive alerts via push and email for every change in the system. --- ## Employees URL: https://documentation.skillsworkflow.com/docs/administration/importing-data/employees Summary: In this article, we walk you through the simple steps required to efficiently import your employee data, ensuring a smooth onboarding process. In this article, we walk you through the simple steps required to efficiently import your employee data, ensuring a smooth onboarding process. The employee importation process will: - Create an employee - Link the employee to the User and Company To import the data successfully, ensure that there is no duplicated entries in the system. The following combination must be unique: - Name | Company | User | External Id | Max Value | Active ::: Preparing your data file: - Format your employee data file correctly for seamless importing. - Ensure the data is organized and structured in a compatible format. - Verify that all required fields are included and accurately populated. - Consider any specific data formatting guidelines or restrictions outlined in the system documentation. - Double-check for any inconsistencies or errors in the data to avoid issues during the import process. When importing an employee for a user who is already linked to a resource, a new employee entry will be created. However, please note that: - The old link between user-employee will be removed - visible on the employee list. - The new employee will be linked to the user on the employee list. - The new imported employee will not be automatically updated in the user's profile - field named as "Resource". ::: ### FAQ #### How do I check for duplicated entries? To check for duplicated employees, please follow the next steps: 1. Access the employee list. 2. Export all data to .xls. 3. Open the .xls file and search for duplicated entries. 4. Take note of the duplicated entries that need to be removed. 5. Return to the employee list. 6. Delete the duplicated entries. --- ## Holidays URL: https://documentation.skillsworkflow.com/docs/administration/calendars/holidays Summary: To create a holiday, go to “Maintenance” and look for the “Holiday”. To create a holiday, go to "Maintenance" and look for the "Holiday". Click on the "+" icon located in the upper right corner of the screen. The Holiday creation screen will open. - **Name** - In the name field, enter the name of the holiday and the specific date of the holiday. - **Date** - The date when the holiday will occur. - **Company** - The company field does not need to be filled in, it is only necessary to put the company if it is a group of many companies and this holiday is specific to a company within the group. - **Is Plannable** - Allows the holiday to be visible to users. - **Allows Time Sheets** - Allows users to enter hours on this day. :::note If your company does not allow the insertion of hours in the Timesheet on Holidays, uncheck this option. ::: At the end of the creation process, click OK to save. --- ## Maintenance URL: https://documentation.skillsworkflow.com/docs/administration/maintenance Summary: Maintenance is Skills Workflow's back-office configuration module. Its catalogue groups every configuration entry into areas, so administrators and consultants can browse or search for the screen they need. ## Overview Maintenance is the back-office module where administrators and consultants configure Skills Workflow: organisation structure, permissions, pricing, workflow stages, screens, integrations and other reference data. The **Maintenance catalogue** organises every configuration entry into areas, so a specific screen can be found by browsing its area or by searching for it directly, instead of scrolling a single long menu. ## Accessing Maintenance 1. Click your user avatar in the top-right corner of the main menu. 2. Select **Maintenance**. ## How to use the catalogue ### Browse by area The **Browse by area** panel on the left lists every maintenance category, each with a count of the configuration entries it holds. Selecting a category loads its entries under **Configuration entries**. See [Areas in the Maintenance catalogue](#areas-in-the-maintenance-catalogue) for the full list. ### Search all entries The **Search all Maintenance entries** field matches across every area at once, not only the selected one. Each result shows the area it belongs to, so an entry can be opened without knowing its category first. ### Open a configuration workspace Selecting a card under Configuration entries opens that entry's configuration workspace: - A data grid lists the entry's records, with controls to add a record, filter, search within the grid, and group rows by a column. - The row count is shown at the bottom of the grid. - Selecting a row opens a record panel with that record's fields. - Changes are saved from the record panel. - The panel's previous and next controls step through the grid's records without closing the panel. ## Areas in the Maintenance catalogue | Area | Entries | Configuration entries | |---|---|---| | Organisation & locations | 9 | Cities, Companies, Countries, Departments, Disciplines, Divisions, Idiom Groups, Idioms, Languages | | People & permissions | 12 | Achievements, Employees, [Roles](/docs/administration/system-roles-profiles), Teams, [Typologies](/docs/administration/create-typologies), Typology Groups, User Types, User Typology History, [Users](/docs/administration/users/create-user), Users and Clients, Users Last Login, Users Responsibility Chain | | Clients, suppliers & markets | 10 | Billing Clients, Brands, Client Classification, Client Groups, [Clients](/docs/product/commercial/crm/create-commercial-client), Commercial Product Companies, Market Groups, Markets, Sectors, Suppliers | | Pricing, products & finance | 10 | Accounts, Billing Products, Commercial Payment Conditions, Currencies, Payment Conditions, [Price Table Columns](/docs/product/commercial/rates/price-tables), [Price Tables](/docs/product/commercial/rates/price-tables), Products, Rate Card Columns, [Rate Cards](/docs/product/commercial/rates/rate-cards) | | Projects, work & delivery | 16 | Additional Information, Business Object Types, [Description Templates](/docs/administration/description-templates), Document Members, Document Teams, Documents, Expense Types, Job Classifications, Job Types, Link Types, Project Classifications, Project Types, Service Groups, Services, Tags, Templates | | Workflow | 6 | Custom Actions, [Stage Types](/docs/administration/workflows/stage-types), [Stages](/docs/administration/workflows/stages), [Transitions](/docs/administration/workflows/transitions), Workflow Management, [Workflows](/docs/administration/workflows) | | Time, schedules & leave | 6 | [Holiday](/docs/administration/calendars/create-holidays), Leave Infos, [Leave Types](/docs/administration/calendars/create-leave-type), Schedules, Shifts, Work Types | | Reports & output | 4 | Printing Layouts, Queries, Query Preview, Reports | | Screens, lists & workspaces | 4 | List Definitions, Panels, Views, [Workspaces](/docs/build-and-extend/workspaces) | | Media & print production | 4 | Print Size Units, Print Sizes, Publications, Publishers | | System & integrations | 12 | AI Skills, [Automations](/docs/build-and-extend/automations), Configuration, [Custom Tables](/docs/administration/custom-tables), Environment, Integration Logs, Integrators, Marketplace, Notification Types, [SSO](/docs/integrations/single-sign-on-sso), System Parameters, [Webhooks](/docs/build-and-extend/api/webhooks) | | Other | 7 | Chat GPT, Copilot Chat, File System, Marketplace v2, Projects with Inactive Products, Usage Metrics, and other entries not grouped under another area | Entries without a link are not yet covered by a dedicated article. The "Other" area can also hold entries that are specific to a tenant. ## Related articles - [Custom Tables](/docs/administration/custom-tables) - [Description Templates](/docs/administration/description-templates) - [Roles and Profiles](/docs/administration/system-roles-profiles) - [Workflow](/docs/administration/workflows) --- ## Menu URL: https://documentation.skillsworkflow.com/docs/administration/system/menu Summary: On this page you will find how to affect only the icon that appears in the menu. ### Description On this page you will find how to affect only the icon that appears in the menu. To activate one or more properties of the the new menu, the Show new menu button should be enabled Type Required Description Show new menu Boolean false Display the new menu. On Initialized Function false A function used to save the UI component instance. On Item Click Function | String false A function that is executed when a collection item is clicked or tapped. On Showing Function false A function that is executed before the context menu is shown. ## ### Basic Usage ```javascript function onShowing(menus) { let obj = menus.find((a) => a.id == "Contracts"); if (obj) { obj.icon = "fas fa-calendar-alt"; } return menus; } ``` Example --- ## Password Policy URL: https://documentation.skillsworkflow.com/docs/administration/users/password-policy Summary: Setting up the Skills Workflow password policy so native logins meet the company's own security requirements. The Skills Workflow password policy must be properly setup in order to be compliant with the company specific policy (e.g. SOX compliance). This ensures that users can log into Skills Workflow using their native login in a secure manner. It must be setup even if you are using the SSO login at your company. Password policies are under the Configuration: - Navigate to the Configuration from your Profile, and open the Configuration Workspace. - Scroll down to the bottom of the page to the tab Security. Above is an example of the policy settings that can be set: - 8 Characters Password Minimum Length - Must have Digits - Must have Upper and Lower Case - Must have Non-Alphanumeric characters - Insufficient Password Strength Text: - “Password must have a minimum 8 characters and must contain at least one digit and one special character.” --- ## Password recovery via "Forgot your password" option URL: https://documentation.skillsworkflow.com/docs/administration/users/password-recovery Summary: How a user resets their own password from the login page, without help from a maintenance user. When one forgets their password, there is a way to ask for a new password without needing the help of the maintenance user. On the home page below the login options, a text saying "Forgot your Password?" will appear, that when clicked, a new popup will appear so that the user inserts their username. After inserting the Username in the popup an email with the temporary password will be sent, this password must be used when entering in the system and after being used the User will redefine his real password so that must be used from that moment on to access the system. --- ## Products URL: https://documentation.skillsworkflow.com/docs/administration/importing-data/products Summary: Importing product records into Skills Workflow. Products --- ## Projects URL: https://documentation.skillsworkflow.com/docs/administration/importing-data/projects Summary: In this article, we will guide you through the simple steps required to efficiently import projects, ensuring a seamless integration process. In this article, we will guide you through the simple steps required to efficiently import projects, ensuring a seamless integration process. The project import process will: - Create a project associated with the client. - Associate the state defined in the file. To successfully import the data, make sure that the workflow is created with the start and end steps defined. The following combination must be unique: - Name| Number| Client| Product| Currency| Project Owner| Project Type| WorkflowState| Classification| Start Date| End Date ::: Preparing your data file: - Format your data file correctly for a smooth import. - Ensure that the data is organized and structured in a compatible format. - Verify that all mandatory fields are included and filled in correctly. - Consider any specific data formatting guidelines or constraints mentioned in the system documentation. - Thoroughly check for inconsistencies or errors in the data to avoid issues during the import process. --- ## Query URL: https://documentation.skillsworkflow.com/docs/administration/system/team-query Summary: On this page you will find how to create an action of the type Team based in Data Source. ### Description On this page you will find how to create an action of the type Team based in Data Source. Specifies which Users to show in each Team. Includes Department and Typology. Placed as Data Source in the Team. Basic Usage #### Available filters Parameter Type Required Description @AssignmentTypeld Uniqueidentifier false Id of the assignment type @DocumentOid Uniqueidentifier false Id of the document @DocumentTypeName String false Name of the document type @SearchValue string false Search value #### Required fields for Query - UserId - UserName - Name - UserHasImage - TypologyName - DepartmentName ```sql select u.Oid as UserId, u.Name as Username, u.[Name] as [Name], u.HasImage as UserhasImage, uty.Name as TypologyName, dep.Name as DepartmentName from [User] u left join UserTypology uty on u.Typology = uty. [0id] left join Department dep on .Department = dep. [Oid] where u.[Name] like concat('%', @SearchValue, '%') or @SearchValue = '' order bY u.[Name] ``` --- ## Query Mentions URL: https://documentation.skillsworkflow.com/docs/administration/system/query-mentions Summary: On this page you will find how to use mentions based on queries. ### Description On this page you will find how to use mentions based on queries. 1. In SQL playground create the query. 2. Select the query that you created. Example Filters Description @ClientId Id of the client @CurrentUserCompanyId Company of the user @CurrentUserDepartmentId Department of the User @CurrentUserDivisionId Division of the User @CurrentUserId Id of the User DocumentOid Id of the document @SearchValue Search value @DocumentTypeName Name of the document type --- ## Stage Mappings URL: https://documentation.skillsworkflow.com/docs/administration/workflows/stage-mappings Summary: A stage mapping creates an automatic link between stages across different workflows. ## What is a Stage Mapping? A **stage mapping** creates an automatic link between stages across different workflows. When a document reaches a specific stage, the system can automatically move a related document to a different stage. This is essential for **parent–child document relationships**. For example: - When a **Project** reaches "Approved", all its child **Deliverables** should move from "Draft" to "Ready to Start" - When a **Request** reaches "Cancelled", its linked **Estimates** should move to "Cancelled" --- ## How It Works A stage mapping defines: | Property | Description | |----------|-------------| | **Workflow** | The workflow this mapping belongs to. | | **Document In Stage** | The condition — when the related document is in this stage… | | **Set Stage** | …move the current document to this stage. | | **Order** | The evaluation order when multiple mappings exist. | The mapping fires automatically when a document's related document changes stage. No user action is required. --- ## Example Imagine a Deliverable workflow with this mapping: > **When** the parent Project is in stage "Cancelled" > **Then** set the Deliverable to stage "Cancelled" This ensures child documents stay in sync with their parent's lifecycle without manual intervention. --- ## Tips - Mappings are evaluated in **order** — the first matching mapping wins. - A stage mapping only fires when the **related document** changes stage, not the current document. - Use mappings to enforce business rules across document hierarchies (Project → Deliverable → Task). - Be careful with circular mappings — if Document A maps to Document B and vice versa, ensure they don't create infinite loops. --- ## Stage Types URL: https://documentation.skillsworkflow.com/docs/administration/workflows/stage-types Summary: A stage type is the classification attached to a stage. ## What is a Stage Type? A **stage type** is the classification attached to a [stage](stages.md). Every stage must have exactly one stage type. Stage types are used for: - **Reporting** — group and filter documents by stage category rather than individual stage names - **Automation** — trigger rules based on the stage type configured on the current stage - **Visual grouping** — each stage type has its own color, which is used as a fallback when a stage has no custom color --- ## How to Use Stage Types Think of a **stage name** as the specific step users see, such as "Draft", "Waiting for Approval", or "Ready to Invoice". Think of a **stage type** as the broader meaning behind that step. For example: - several different stages may all belong to the same business meaning - reports can group those stages together - automations can react to the type instead of a single stage name This is useful when different teams or document types use slightly different stage names, but you still want the same business behavior. --- ## Default Reference List Skills Workflow includes a default list of stage types. Not every environment will use all of them, but this list is the correct reference when you need the default system values. If you need to confirm which stage types are actually being used in your environment, check [`DE-Stages`](../../build-and-extend/api/data-extraction/de-stages.md). In that query: | Column | Meaning | |--------|---------| | `StageId` | Stage identifier | | `Stage` | Stage name | | `TypeId` | The stage type identifier | | `Type` | The stage type name currently used on that stage | --- ## Default Stage Types View the default stage types | Stage Type | Status | Default Color | |------------|--------|---------------| | `None` | `0` | `#D6D6D6` | | `Draft` | `1` | `#9E9E9E` | | `New` | `2` | `#94DF89` | | `Assigned` | `3` | `#61B73C` | | `InProgress` | `4` | `#8ABEF3` | | `ToApprove` | `5` | `#446FD2` | | `Done` | `6` | `#B5A0E8` | | `Canceled` | `7` | `#B5A0E8` | | `InQuotation` | `8` | `#B9519E` | | `InternallyApproved` | `9` | `#F6DC05` | | `Approved` | `10` | `#F88A07` | | `Production` | `11` | `#FF5E3A` | | `QualityControl` | `12` | `#A2845E` | | `Returned` | `13` | `—` | | `Expired` | `14` | `—` | | `ToPresent` | `15` | `—` | | `NotApproved` | `16` | `—` | | `Hidden` | `17` | `—` | | `Rejected` | `18` | `—` | | `Sent` | `19` | `—` | | `NotBilled` | `20` | `—` | | `WaitYourReference` | `21` | `—` | | `Billing` | `22` | `—` | | `PartiallyBilled` | `23` | `—` | | `Billed` | `24` | `—` | | `Activated` | `25` | `—` | | `Deactivated` | `26` | `—` | | `ExternalRefused` | `27` | `—` | | `ToIntegrate` | `28` | `—` | | `Integrated` | `29` | `—` | | `PartiallyApproved` | `30` | `—` | | `Current` | `31` | `—` | | `ToEmit` | `32` | `—` | | `Invoiced` | `33` | `—` | | `NotExpectingInvoice` | `34` | `—` | | `PartiallyInvoiced` | `35` | `—` | | `PartiallyPaid` | `36` | `—` | | `Paid` | `37` | `—` | --- ## Properties | Property | Description | |----------|-------------| | **TypeId** | The unique identifier of the stage type. This is mainly useful for APIs, exports, or integrations. | | **Name** | The stage type name used in the system. | | **Status** | The numeric reference for the stage type. This is useful when working with APIs, imports, exports, or technical mappings. | | **Color** | The default color used for stages with this type, unless the stage has its own color. | ## Good Practice - Keep stage names user-friendly, but keep stage types consistent. - Reuse the same stage type for stages that have the same business meaning. - Before creating reports or integrations, confirm the values used in your environment with [`DE-Stages`](../../build-and-extend/api/data-extraction/de-stages.md). --- ## Stages URL: https://documentation.skillsworkflow.com/docs/administration/workflows/stages Summary: A stage represents a state that a document can be in at any point during its lifecycle. ## What is a Stage? A **stage** represents a state that a document can be in at any point during its lifecycle. For example, a Deliverable might pass through stages like *Draft*, *In Review*, *Approved*, and *Closed*. Every workflow is built from a sequence of stages connected by [transitions](transitions.md). --- ## Properties | Property | Description | |----------|-------------| | **Name** | The display name of the stage (e.g. "In Review"). | | **Color** | A hex color used to visually distinguish the stage in the UI. | | **Order** | Determines the display order. Must be unique within the document type. | | **Stage Type** | Classifies the stage — see [Stage Types](stage-types.md). | | **Delayed** | Marks the stage as a delay indicator for reporting. | | **Visible to Client** | Whether external client users can see documents in this stage. | | **Allows Timesheet** | Whether users can log time against documents in this stage. | | **Percentage** | A completion percentage (0–100) associated with this stage. | | **Suggest Percentage** | If enabled, the system auto-suggests the stage percentage when a transition fires. | --- ## Stage Teams Each stage can have **team assignments** that control who can interact with documents at that stage. A stage team links an **assignment type** (e.g. Requester, Executor, Reviewer) to a set of permissions: | Permission | Description | |------------|-------------| | **Allow Read** | The team can view the document. | | **Allow Write** | The team can edit the document. | | **Allow Pending** | The team receives pending/task notifications. | | **Must Send Notification** | A notification is sent to team members when a document enters this stage. | Use stage teams to enforce that only the right people can see and edit documents at each step. For example, only the *Executor* team might have write access during the "In Production" stage. --- ## Translations Stage names can be **translated** so they appear in each user's interface language. The system stores localized names per language code (e.g. `en`, `pt`, `es`). For example, a stage named "Approved" might have: - **EN**: Approved - **PT**: Aprovado - **ES**: Aprobado --- ## Tips - The **initial stage** is the stage where new documents are created (e.g. "Draft"). - The **final stage** is the terminal state (e.g. "Closed" or "Completed"). - Stages referenced by [transitions](transitions.md) cannot be deleted until those transitions are removed first. - Use [stage types](stage-types.md) to group stages for reporting and automation rules. --- ## System Roles and Profiles URL: https://documentation.skillsworkflow.com/docs/administration/roles-and-profiles Summary: How access is controlled in Skills Workflow: what a Role grants, and how Profiles group roles for a user. ## User accesses are defined by Roles - Virtually anything in Skills Workflow can be controlled by specific roles. - That means that you can go as further as specified for every single user, what he can or cannot see or change. - All you need to do is grant him or deny him a role ## Categories of roles There are 7 categories of roles, which define what you can or cannot do with a certain module or document. | Role Category | Action | | ------------- | ----------- | | `Read` | Gives you read-only rights, i.e you can see but cannot change | | `Write` | Allows you to edit or modify | `Create` | Allows you to create | `Save` | Includes the Read, Write and Create | `Navigate` | Allows you to navigate to a certain module | `All` | Grants you access to all documents/data in a certain module | `Approve` | Gives you access to do approvals on a specified module These suffixes together with the document or module name constitute the role itself. E.g. The role TimesheetNavigate will allow you to navigate to the Timesheet module. ## System Documents - Client - Access to client - Chat - Access to chat - Crm - Access to the Clients List - Contracts - Access to Fees - Deliverable - Access to Jobs - Estimate - Access to Estimates - Expense - Access to Expenses - Project - Access to Projects - Ratecard - Access to Ratecards - Report - Access to Reports - Files - Access to files uploaded on documents - Gantt - Access to the Gantt chart - Assignment - Access to Team Assignments - Timesheet - Access to Timesheets - Vacation - Access to Leaves ## Maintenance Documents - AccountGroup - Account Management - Costs - Billing Product - Billing Client - Custom Views ## Creating Profiles You can group a set of roles into what we call a Profile. - Instead of granting the users loose roles, you give them pre-set Profiles instead. - Profiles make user accesses much easier to maintain and control. - Profiles are also completely customizable in terms of roles inside and also naming. A typical example is the Account Profile which is comprised by the roles: DeliverableSave, ChatSave, EstimateRead, ProjectSave, VacationSave, TimesheetSave, TimesheetApprove, GanttSave. ## Standard Profiles We have a standard list of Profiles that come by default in Skills Workflow. | Profile | Standard Rights | | ------------- | ----------- | | `Requester Profile` | Given to whoever will create Jobs and Projects. Typically all Accounts. | | `Responsible Profile` | Give to supervisors that will not create Projects or Jobs but will add their inputs. E.g. Department Heads. | | `Executor Profile` | Given to actual executors such as creatives, copywriters, producers, etc. | | `Finance Profile` | Given to finance users which usually have full visibility over everything. | | `HR Profile` | Given to anyone from Human Resources which will do the maintenance of user leaves. | | `MaintenanceAccessProfile` | Given to IT's who will be the administrators of the system. | | `MaintenanceReadProfile` | Given to IT's who will be the administrators of the system. | ## Document Access Control - General Considerations Document specific roles are always validated before the access control rules. For instance, in a Project read operation, if the User does not have the ProjectRead role (document or module name with the operation suffix to check) then it does not have read access to any Project and rules will not apply. Each document operation is validated by a specific type of role: | Document Operation | Type of Role | | ------------- | ----------- | | Read Operations | Read roles | | Create Operations | Create roles | | Write Operations | Write roles | | Delete Operations | Write roles | | List Operations | Navigate roles | Document Access can have two sets of rules. Default rules define the initial set over which the Team Access rules will apply ## All Access Roles Rules A Document is only accessible if the User has access to at least the Document's Company. A Draft Document is accessible only to the User which created it. If the user does not have All Access Role it will have access only to documents where the User is currently assigned and the assignment type allows read or write access in the document Stage; If the user has All Access Role: it will have access to all documents, respecting the document's hierarchy. ### AllAccess Document Roles Hierarchy Examples | Cenario | Result | | ------------- | ----------- | | 1 - If the User does not have `AllProjectsAccess` Role | It has access only to Projects where the User is currently assigned and the assignment type allows read or write access in the Project Stage | | 2 - If the User has `AllProjectsAccess` Role but not AllClientsAccess Role | It has access to all Projects for Commercial Clients which the User has access plus all Projects from rule 1 | | 3 - If the User has `AllProjectsAccess` Role and AllClientsAccess Role | It has access to all Projects | | 4 - If the User does not have `AllJobsAccess` Role | It has access only to Jobs where the User is currently assigned and the assignment type allows read or write access in the Job Stage; | 5 - If the User has `AllJobsAccess` Role but not AllProjectsAccess Role | It has access to all Jobs for Projects where the User is currently assigned and the assignment type allows read or write access in the Project Stage plus all Jobs from rule 1 | | 6 - If the User has `AllJobsAccess` Role and AllProjectsAccess Role but not AllClientsAccess Role | It has access to all Jobs from all Projects for Commercial Clients which the User has access plus all Jobs from rule 2 plus all Jobs from rule 1 | | 7 – If the User has `AllJobsAccess` Role, AllProjectsAccess Role, and AllClientsAccess Role | It has access to all Jobs ### No hierarchy All Access Examples - Price Tables - Supplier Notes - Client Credit Notes - Supplier Invoices - Rate Cards - Purchase Orders - Bills | Cenario | Result | | ---------------- | ----------- | | 8 - If the User does not have `AllSupplierNotesAccess` Role | It has access only to Supplier Notes where the User is currently assigned and the assignment type allows read or write access in the Supplier Note Stage | | 9 – If the User has `AllSupplierNotesAccess` Role | It has access to all Supplier Notes inside the User Company, as this document has no hierarchy | --- ## Transitions URL: https://documentation.skillsworkflow.com/docs/administration/workflows/transitions Summary: A transition defines a path that moves a document from one stage to another within the same workflow. ## What is a Transition? A **transition** defines a path that moves a document from one [stage](stages.md) to another within the same workflow. For example, "Submit for Review" might move a document from *Draft* to *In Review*. Transitions are the core mechanism for controlling **how** and **when** documents progress through their lifecycle. --- ## Properties | Property | Description | |----------|-------------| | **Name** | The display name shown to users (e.g. "Approve", "Reject"). | | **From Stage** | The stage the document must be in to execute this transition. | | **To Stage** | The stage the document will move to after execution. | | **Order** | Display order in the UI when multiple transitions are available. | | **Icon** | An optional icon displayed next to the transition button. | | **Is Default** | Whether this is the default transition (pre-selected in the UI). | | **Request Confirmation** | If enabled, shows a confirmation dialog before executing. | | **Message Text** | Custom message shown in the confirmation dialog. | | **Comment Required** | The user must enter a comment to execute the transition. | | **Hours Required** | The user must log hours before executing the transition. | | **File Upload Required** | The user must upload a file before executing the transition. | | **File Upload Folder** | The target folder for required file uploads. | | **User Must Be In Team** | Only users who are in the document's team can execute the transition. | | **Must Send Notification** | A notification is sent when the transition executes. | --- ## Transition Roles Transitions can be **restricted by security role**. Only users who have one of the allowed roles can execute the transition. | Property | Description | |----------|-------------| | **Role** | The security role allowed to execute the transition. | | **Check Limits** | If enabled, the role is only valid within a value range. | | **Start Value / End Value** | The value range for limit-based restrictions (e.g. approval amount limits). | You can set up a transition "Approve" that is only available to users with the "Manager" role, and a separate "Approve (Senior)" transition for amounts above €50,000 that requires the "Director" role with appropriate limit values. --- ## Transition Motives A **motive** is a reason the user must select when executing a transition. Motives are typically used for rejections or cancellations to capture structured feedback. | Property | Description | |----------|-------------| | **Description** | The motive text shown to the user (e.g. "Budget exceeded", "Client request"). | | **Active** | Whether this motive is currently available for selection. | --- ## Transition Custom Actions **Custom actions** are scripts or plugins that execute when a transition fires. They extend the workflow with custom business logic beyond the built-in action types. --- ## Validation Query A transition can have a **validation query** that checks whether the transition is allowed to proceed. The query receives the current document's ID and must return `1` if the transition can be executed. This is useful for enforcing business rules that go beyond simple role and stage checks. | Parameter | Type | Description | |-----------|------|-------------| | `CurrentDocumentId` | Uniqueidentifier | The ID of the document attempting the transition. | The query should return `1` if valid. If invalid, it can return a message explaining why the transition was blocked. Configure the validation query in the **Validate Query Name** field of the transition. --- ## Transition Actions **Actions** are automated operations that fire when a transition executes. Each action has a **type** that determines what it does. A transition can have multiple actions that run in sequence. ### How to Use When configuring a transition action: 1. Select the **Action Type** from the list below 2. Some actions require an **Options** value (typically a query name) 3. The action fires automatically when the transition executes ### Data-Source Actions These actions execute a query and use the results to perform operations. Configure them by setting the Options field to the name of your query. #### Block / Unblock Documents Blocks or unblocks a list of documents returned by a query. **Action Types:** `BlockDocuments`, `UnblockDocuments`, `Block`, `Unblock`, `BlockChildren`, `UnblockChildren` | Query Parameter | Type | Description | |----------------|------|-------------| | `CurrentDocumentId` | Uniqueidentifier | The ID of the document executing the transition. | --- #### Change Documents Stage Changes the stage of documents returned by a query to a specified target stage. **Action Types:** `ChangeDocumentsStage`, `ChangeChildTaskStage`, `ChangeJobsStage`, `ChangeProjectStage`, `ChangeProjectsStage`, `ChangeEstimatesStage`, `ChangePurchaseOrderStage`, `ChangeBillStage`, `ChangeRelatedEstimateStage`, `SetChildrenStage`, `SetParentStage`, `UpdateParentStage` The query must return these columns: | Column | Type | Description | |--------|------|-------------| | `DocumentTypeName` | String | The document type (e.g. "Deliverable", "Project"). | | `DocumentId` | Uniqueidentifier | The ID of the document to update. | | `WorkflowStageId` | Uniqueidentifier | The target stage ID. | SQL Example — Cancel child deliverables when parent is cancelled ```sql SELECT 'Deliverable' AS DocumentTypeName, sd.Oid AS DocumentId, ws.Oid AS WorkflowStageId FROM Deliverable d JOIN WorkflowState dws ON dws.Oid = d.WorkflowState JOIN Deliverable sd ON sd.Parent = d.Oid JOIN WorkflowState sdws ON sdws.Oid = sd.WorkflowState JOIN Document doc ON doc.TypeName = 'Skill.Module.BusinessObjects.Deliverable' JOIN WorkflowState ws ON ws.Document = doc.Oid AND ws.Name = 'Cancelled' WHERE d.Oid = @CurrentDocumentId AND sdws.Name NOT IN ('Delivered', 'Completed', 'Cancelled') ``` --- #### Assign Team Assigns users to teams on the current document based on query results. **Action Types:** `AssignTeam`, `Assign`, `RequiredAssign`, `AssignDepartmentTeam`, `AssignJobTypeTeam`, `AssignCreatedByTeam`, `AssignCommercialClientProjectManagerTeam`, `AssignTeamFromClientMarkets`, `AssignTeamFromClientBrands`, `AssignAdminResponsible` | Query Parameter | Type | Required | Description | |----------------|------|----------|-------------| | `CurrentDocumentId` | Uniqueidentifier | Yes | The document executing the transition. | | `CurrentUserId` | Uniqueidentifier | No | The user triggering the transition. | The query must return: | Column | Type | Description | |--------|------|-------------| | `UserId` | Uniqueidentifier | The user to assign. | | `TeamId` | Uniqueidentifier | The assignment type (team) to place the user in. | --- ### All Action Types Reference Below is the complete list of action types available for transitions, organized by category. - Multiple values are separated by **semicolons** (`;`) - Stage names, team names, and query names are **case-sensitive** - A dash (—) in the Options column means no configuration is needed #### Stage & Status Changes | Action Type | Description | Options | |-------------|-------------|---------| | `CompleteState` | Marks the current state as complete. | — | | `ChangeDependentTaskStatusTo` | Changes the status of dependent tasks. | `StageName` — target stage name. Defaults to `Ready` if empty. | | `ChangeChildTaskStage` | Changes the stage of child tasks. | — (uses the transition's target stage) | | `ChangeJobsStage` | Changes the stage of related jobs. | `ToStageName;IgnoreStage1;IgnoreStage2;...` — first value is the target stage; remaining values are stages to skip. **Required.** | | `ChangeProjectStage` | Changes the stage of the parent project. | `StageName` — target project stage. | | `ChangeProjectsStage` | Changes the stage of multiple projects. | `ToStageName;IgnoreStage1;IgnoreStage2;...` — same pattern as ChangeJobsStage. | | `ChangeEstimatesStage` | Changes the stage of related estimates. | `ToStageName;IgnoreStage1;IgnoreStage2;...` — same pattern as ChangeJobsStage. | | `ChangePurchaseOrderStage` | Changes the stage of related purchase orders. | `ToStageName;IgnoreStage1;IgnoreStage2;...` — same pattern as ChangeJobsStage. | | `ChangeBillStage` | Changes the stage of related bills. | `ToStageName;IgnoreStage1;IgnoreStage2;...` — same pattern as ChangeJobsStage. **Required.** | | `UpdateParentStage` | Updates the parent document's stage. | `ToStageName;IgnoreStage1;IgnoreStage2;...` — same pattern as ChangeJobsStage. **Required.** | | `ChildrenStageIn` | **Validation only** — blocks the transition if any child is NOT in one of the listed stages. | `StageName1;StageName2;...` — allowed stage names. **Required.** | | `SetChildrenStage` | Sets all children to a specific stage. | `ToStageName;IgnoreStage1;IgnoreStage2;...` — same pattern as ChangeJobsStage. **Required.** | | `SetParentStage` | Sets the parent document to a specific stage. | `ToStageName;IgnoreStage1;IgnoreStage2;...` — same pattern as ChangeJobsStage. | | `ChangeDocumentsStage` | Changes the stage of documents returned by a query. | `QueryName1;QueryName2;...` — semicolon-separated query names. Each query must return `DocumentTypeName`, `DocumentId`, `ToWorkflowStageName`. | | `ChangeRelatedEstimateStage` | Changes the stage of the related estimate. | `ExternalId` — the ExternalId on the stage transition to match. | | `ChangeRelatedQuoteStatus` | Changes the status of related quotes. | `true` or `false` — `true` approves, `false` disapproves quote items. | | `ChangeEstimateExternalStatusTo` | Updates the external status of an estimate. | `StatusValue` — the external status value to set. | | `ChangeDeliverableExternalStatusTo` | Updates the external status of a deliverable. | `StatusValue` — the external status value to set. | | `ChangeDeliverableOrEstimateExternalStatusTo` | Updates the external status of a deliverable or estimate. | `StatusValue` — the external status value to set. | #### Team & Assignment | Action Type | Description | Options | |-------------|-------------|---------| | `Assign` | Assigns users to teams (handled in the UI). | — | | `RequiredAssign` | Validates that team assignments exist — blocks the transition if not. | — | | `AssignAdminResponsible` | Assigns the admin responsible user. | `TeamName1;TeamName2;...` — teams to assign admin responsibles into. | | `UpdateProjectAssignments` | Synchronizes project team assignments. | — | | `CopyTeamFromRequest` | Copies the team from the linked request. | `TeamName1;TeamName2;...` — team names to copy. **Required.** | | `CopyTeamFromParent` | Copies the team from the parent document. | `TeamName1;TeamName2;...` — team names to copy. **Required.** | | `AssignTeamFromClientMarkets` | Assigns teams based on client market configuration. | `ColumnName;TeamName1;TeamName2;...` — first value is the column name on the client markets table; remaining are team names. **Required.** | | `CopyFromTeamToTeam` | Copies members from one team to another. | `FromTeam;ToTeam;RemoveFrom;RemoveTo` — first two **required**; `RemoveFrom` / `RemoveTo` are optional booleans (`true`/`false`). | | `MoveFromTeamToTeam` | Moves members from one team to another. | `FromTeam;ToTeam` — both **required**. | | `RemoveTeam` | Removes all members from a team. | `TeamName` — the team to clear. **Required.** | | `CopyTeamToFinancialCreatedDocuments` | Copies the team to newly created financial documents. | `FromTeam;ToTeam` — used as companion to Invoice/InvoiceJob. | | `CopyTeamToCreatedPurchaseOrders` | Copies the team to newly created purchase orders. | `FromTeam;ToTeam` — used as companion to Buy. | | `AssignTeamFromClientBrands` | Assigns teams based on client brand configuration. | `ColumnName;TeamName1;TeamName2;...` — same pattern as AssignTeamFromClientMarkets. **Required.** | | `AssignTeam` | Assigns users to teams via query (data-source action). | `QueryName1;QueryName2;...` — queries must return `UserId`, `TeamId`. | | `CopyFromTeamToTeamByQuery` | Copies team members using a query to determine source/target. | `QueryName;FromTeam;ToTeam;RemoveFrom;RemoveTo` — QueryName and FromTeam **required**; ToTeam, RemoveFrom (bool), RemoveTo (bool) optional. | | `AssignDepartmentTeam` | Auto-assigns the department's default team. | `QueryName;TeamName1;TeamName2;...` — query returning `UserId`, `TeamId`, plus optional team names. | | `AssignJobTypeTeam` | Auto-assigns the job type's default team. | `QueryName;TeamName1;TeamName2;...` — same as AssignDepartmentTeam. | | `AssignCreatedByTeam` | Assigns the document creator to a team. | `QueryName;TeamName1;TeamName2;...` — same as AssignDepartmentTeam. | | `AssignCommercialClientProjectManagerTeam` | Assigns the commercial client's project manager. | `QueryName;TeamName1;TeamName2;...` — same as AssignDepartmentTeam. | #### Block & Unblock | Action Type | Description | Options | |-------------|-------------|---------| | `Block` | Blocks the current document. | `type1;type2;...` — block types: `document`, `team`, `workflow`, `comment`. Defaults to `document` if empty. | | `Unblock` | Unblocks the current document. | `type1;type2;...` — same as Block. | | `BlockChildren` | Blocks all child documents. | `type1;type2;...` — same as Block. | | `UnblockChildren` | Unblocks all child documents. | `type1;type2;...` — same as Block. | | `BlockDocuments` | Blocks documents returned by a query. | `QueryName;type1;type2;...` — first value is the query name; remaining are block types. Defaults to `document` if no types specified. | | `UnblockDocuments` | Unblocks documents returned by a query. | `QueryName;type1;type2;...` — same as BlockDocuments. | #### Estimates & Financial | Action Type | Description | Options | |-------------|-------------|---------| | `CreateEstimate` | Creates an estimate from the current document. | — | | `Buy` | Triggers a buy/purchase operation. | `CancelWorkflowStageName` — stage name for cancelling existing POs before re-purchasing. Optional. | | `Invoice` | Triggers an invoice generation. | — | | `InvoiceJob` | Generates an invoice for a specific job. | `CanInvoiceQueryName;InvoiceSeveral` — optional query name to validate; `InvoiceSeveral` is a boolean to allow multiple invoices. | | `Credit` | Creates a credit note. | — | | `ApproveItems` | Approves estimate line items. | — | | `DisapproveItems` | Rejects (disapproves) estimate line items. | — | | `SynchronizeEstimateStageAndHistory` | Syncs the estimate stage with its history. | — | | `CreateEstimateVersion` | Creates a new version of the estimate. | — | | `CloseProjectEstimates` | Closes all estimates under the project. | — | | `EstimateMerge` | Merges multiple estimates. | `DeleteOnCancel;IgnoreStage1;...` — first element can be `DeleteOnCancel` (case-insensitive) or a stage name; remaining are stages to ignore. Optional. | | `EstimateUnmerge` | Reverses an estimate merge. | — | | `CreateEstimatesFromRequest` | Creates estimates from a request document. | `QueryName;UpdateValuesQueryName` — first = query name (defaults to `CreateEstimatesFromRequest`); second = optional query for updating field values. | | `ExceedsBudget` | Checks if the document exceeds the budget. | `QueryName;RoleName` — query returning a boolean + error message; optional role name for permission bypass. | | `UpdateRealPlannedCost` | Recalculates real vs. planned costs. | — | #### Planned Time & Workloads | Action Type | Description | Options | |-------------|-------------|---------| | `CreatePlannedHoursFromEstimateItemDetails` | Creates planned hours from estimate items. | — | | `DeletePlannedHoursFromEstimateItemDetails` | Removes planned hours from estimate items. | — | | `CreatePlannedCostsFromEstimateItemDetails` | Creates planned costs from estimate items. | — | | `DeletePlannedCostsFromEstimateItemDetails` | Removes planned costs from estimate items. | — | | `CreatePlannedDeliverables` | Creates planned deliverables from the estimate. | `JobSubjectAs` — controls the job subject format. Defaults to `EstimateItemDescription` if empty. | | `AddHoursToTimesheet` | Adds hours to the user's timesheet. | `FromWorkflowStateName` — the workflow stage name to calculate hours from. **Required.** | | `CreatePlannedHoursDeliverableFromEstimateItemDetails` | Creates deliverable-level planned hours. | — | | `DeletePlannedHoursDeliverableFromEstimateItemDetails` | Removes deliverable-level planned hours. | — | | `DeleteDailyWorkloads` | Deletes daily workload entries. | — | | `CreateJobPlannedHoursFromEstimateItemDetails` | Creates job-level planned hours from estimate items. | — | | `DeleteJobPlannedHoursFromEstimateItemDetails` | Removes job-level planned hours from estimate items. | — | #### User Interaction & Popups | Action Type | Description | Options | |-------------|-------------|---------| | `RequestMotive` | Shows a motive selection popup. | `MotiveId1;MotiveId2;...` — (optional) restricts selectable motives to the listed IDs. If empty, all motives are available. | | `RequestReference` | Prompts the user to enter a reference. | — | | `RequestMotiveWithRequestedDate` | Shows a motive popup that also asks for a requested date. | — | | `RequestComment` | Prompts the user to enter a comment. | — | | `RequestFlaggedAssignment` | Prompts for a flagged assignment selection. | `AssignmentType1;AssignmentType2;...` — (optional) restricts selectable assignment types. | | `RemoveFlaggedAssignments` | Removes existing flagged assignments. | — | | `RequestClientUserFields` | Shows a popup with client-specific user fields. | `FieldName1;FieldName2;...` — list user field names to make them **required** in the popup. If empty, all user fields are optional. | | `RequestUserFields` | Shows a popup with user-defined fields. | `FieldName1;FieldName2;...` — list user field names to make them **required** in the popup. If empty, all user fields are optional. | #### Document & Field Management | Action Type | Description | Options | |-------------|-------------|---------| | `CreateVersion` | Creates a new version of the document. | `IncrementParent` — if set to `IncrementParent` on estimates, versions the parent estimate instead. Optional. | | `FileUpload` | Triggers a file upload dialog. | — | | `Returned` | Marks the document as returned. | — | | `Request` | Creates a request from the current document. | — | | `ActivateDocument` | Activates a deactivated document. | — | | `Canceled` | Marks the document as cancelled. | — | | `ResetUserFields` | Resets all user-defined fields to their defaults. | — | | `ChangeClassification` | Changes the document's classification. | `ClassificationName` — the target classification name. **Required.** | | `SyncApprovalStatus` | Synchronizes the approval status. | — | | `ChangeEndDateToCurrentDay` | Sets the document's end date to today. | — | | `IncreaseVersionDigit` | Increments the version number. | `Digit;UserFieldColumnName` — `Digit` is the 1-based position; `UserFieldColumnName` is the user field to update (e.g. `uf_version`). **Required.** | | `DecreaseVersionDigit` | Decrements the version number. | `Digit;UserFieldColumnName` — same as IncreaseVersionDigit. **Required.** | | `UnlinkRequest` | Removes the link to the originating request. | — | | `CustomTableWrite` | Writes data to a custom table. | `CustomTableName;QueryName` — both **required**. First = custom table name; second = query returning rows to write. | | `UpdateUserFields` | Updates user-defined fields via query. | `QueryName1;QueryName2;...` — queries must return `ColumnName`, `Value`, `DataTypeId`, and optionally `DocumentId` + `DocumentTypeName`. | | `UpdateFields` | Updates document fields via query. | `QueryName` — query must return `DocumentId`, `DocumentTypeName`, `FieldName`, `FieldValue`. | | `UpdateFieldsValues` | Updates specific field values. | `QueryName1;QueryName2;...` — queries must return column names, values, `ActionType`, and `DocumentTypeName`. | #### Document Creation & Automation | Action Type | Description | Options | |-------------|-------------|---------| | `CreateJobsFromEstimateDeliverableQuantity` | Creates jobs based on estimate deliverable quantities. | `FromTeam;ToTeam;UpdateValuesQueryName` — optional. FromTeam/ToTeam for copying assignments; query name for updating field values on created jobs. | | `CreateTasksFromJobType` | Creates tasks based on the job type template. | `TemplateName;FromTeam;ToTeam;CheckQuery;CreateQuery` — first value is the template name (**required**); remaining are optional. | | `CreateDeliverablesFromRequest` | Creates deliverables from a request. | `QueryName` — defaults to `CreateDeliverablesFromRequest` if empty. | | `CreateProjectFrom` | Creates a project from the current document. | `QueryName` — defaults to `CreateProjectFromRequestWorkflowAction` if empty. | | `CopyDescriptionFrom` | Copies the description from a related document. | `QueryName` — query must return `DocumentId`, `DocumentTypeName`. **Required.** | | `Automation` | Runs an automation rule. | `AutomationId;QueryName` — first = GUID of the automation (**required**); second = optional query name providing payload JSON. | | `SetCompanies` | Sets the companies on the document. | `QueryName` — query returning `CompanyId` rows. | #### External Integration | Action Type | Description | Options | |-------------|-------------|---------| | `SendToExternal` | Sends data to an external integration. | — | | `ToIntegrate` | Marks the document for integration processing. | — | | `SendToExternalKeepOnError` | Sends to external but keeps the document on error (does not roll back). | — | #### SAP Integration | Action Type | Description | Options | |-------------|-------------|---------| | `SendToSap` | Sends the document to SAP. | — | | `ApproveOnSap` | Approves the document on SAP. | — | | `RejectOnSap` | Rejects the document on SAP. | — | | `SendApproveOnSap` | Sends and approves on SAP in one step. | — | | `ApproveProductionOnSap` | Approves production on SAP. | — | | `CancelOnSap` | Cancels the document on SAP. | — | | `ActivateOnSap` | Activates the document on SAP. | — | --- ## Typologies URL: https://documentation.skillsworkflow.com/docs/administration/importing-data/typologies Summary: In this article, we will guide you through the simple steps required to efficiently import typology data, ensuring a seamless onboarding process. In this article, we will guide you through the simple steps required to efficiently import typology data, ensuring a seamless onboarding process. The process of importing the typologies: - Navigate to Maintenance - And search for the Typologies list To import the data correctly, make sure there are no duplicate entries in the system. The following combination must be unique: - Name | Company | Division | Department Type | Department | Plannable | Active ::: Prepare your data file: - Format your typology data file correctly for a smooth import. - Ensure that the data is organized and structured in a compatible format. - Verify that all mandatory fields are included and filled in correctly. - Take into account any specific data format guidelines or restrictions mentioned in the system documentation. - Check for inconsistencies or errors in the data to prevent issues during the import process. ### FAQ #### How can I check for duplicate entries? To check for duplicate typologies, follow the steps outlined below: 1. Access the list of typologies. 2. Export all data to .xls. 3. Open the .xls file and look for duplicate entries. 4. Make note of the duplicate entries that need to be removed. 5. Return to the typologies list. 6. Delete the duplicate entries. --- ## Typology groups URL: https://documentation.skillsworkflow.com/docs/administration/importing-data/typology-groups Summary: In this article, we will guide you through the simple steps required to efficiently import typology group data, ensuring a smooth onboarding process. In this article, we will guide you through the simple steps required to efficiently import typology group data, ensuring a smooth onboarding process. The typology group import process: - Navigate to Maintenance. - And search for the Typology Group listing. To import the data correctly, please ensure there are no duplicate entries in the system. The following combination must be unique: - Name | Company | Active ::: Prepare your data file: - Properly format your typology group data file for a smooth import. - Ensure the data is organized and structured in a compatible format. - Verify that all mandatory fields are included and filled in correctly. - Take into account any specific data format guidelines or restrictions mentioned in the system documentation. - Check for inconsistencies or errors in the data to prevent issues during the import process. ### FAQ #### How can I check for duplicate entries? To check for duplicate typology groups, follow these steps: 1. Access the typology group list. 2. Export all data to .xls. 3. Open the .xls file and look for duplicate entries. 4. Make note of duplicate entries that need to be removed. 5. Return to the typology group list. 6. Delete the duplicate entries. --- ## Upload a profile picture URL: https://documentation.skillsworkflow.com/docs/administration/users/upload-a-picture Summary: Choose a photo to use as your Skills Workflow profile picture, and replace it from your Profile page. You can choose a photo to set as your Skills Workflow profile picture. This picture will be used as the icon for your account and will represent you in Skills Workflow. The recomended format is PNG 180x180 (square image). It will be displayed next to your username in the chat list and every time you do an action in the system (create/edit a project/job, make a comment, upload a file, etc.). ## To upload or replace you profile picture: - Login into Skills Workflow - Go the upper right-hand corner and click on top of your username - Select the option “Profile”. Click on the button called “Change Image” and upload a file from your computer. - Click open to apply changes. --- ## Users URL: https://documentation.skillsworkflow.com/docs/administration/importing-data/users Summary: In this article, we will guide you through the simple steps necessary to efficiently import user data, ensuring a seamless integration process. In this article, we will guide you through the simple steps necessary to efficiently import user data, ensuring a seamless integration process. The user import process will: - Create a user - Associate the user with the company, division, department, and typology. To successfully import the data, ensure that there are no duplicate entries in the system. The following combination must be unique: - Username | Name | IsActive | Company | Division | Department | DepartmentType| Typology ::: Preparing your data file: - Format your user data file correctly for a smooth import. - Ensure that the data is organized and structured in a compatible format. - Verify that all mandatory fields are included and filled in correctly. - Consider any specific data formatting guidelines or constraints mentioned in the system documentation. - Check carefully for inconsistencies or errors in the data to avoid issues during the import process. ### FAQ #### How do I check for duplicate entries? To check for duplicate users, follow the steps below: 1. Access the list of users. 2. Export all data to an .xls file. 3. Open the .xls file and look for duplicate entries. 4. Make a note of the duplicate entries that need to be removed. 5. Return to the list of users. 6. Delete the duplicate entries. --- ## Workflow URL: https://documentation.skillsworkflow.com/docs/administration/workflows Summary: Workflows define how documents move through their lifecycle in Skills Workflow. ## Overview Workflows define how documents move through their lifecycle in Skills Workflow. Every document type — Projects, Deliverables, Estimates, and others — has its own workflow that controls which stages it passes through and what happens at each step. ### Purpose A workflow lets you model the approval and processing steps for any document type. You decide: - What **stages** exist (e.g. Draft, In Review, Approved, Closed) - Which **transitions** connect those stages (e.g. “Submit for Review” moves from Draft → In Review) - What **actions** run automatically when a transition fires (send emails, update fields, create child documents) - Who is **allowed** to execute each transition (role-based permissions) - Whether a **reason** (motive) must be provided ### Use Cases - Design approval flows for creative deliverables - Set up multi-step review and sign-off processes - Automate notifications and field updates when documents change stage - Restrict stage transitions to specific security roles - Require motives for rejections or cancellations - Map stages across related workflows (e.g. a Project and its Deliverables) --- ## Entity Map The interactive diagram below shows how workflow entities relate to each other. Use the dropdown to focus on a specific entity, or click any node to learn more about it. --- ## Key Concepts ### Workflow The top-level container. Each document type has exactly one workflow with an initial and final stage. ### [Stages](stages.md) The states a document passes through (e.g. Draft, In Review, Approved). Includes team permissions, translations, and visibility settings. [Read more →](stages.md) ### [Stage Types](stage-types.md) Classify stages so reporting, automation, and visual rules stay consistent across the workflow. [Read more →](stage-types.md) ### [Transitions](transitions.md) Paths between stages. Configure actions, role restrictions, motives, validations, custom actions, and over 100 built-in action types. [Read more →](transitions.md) ### [Stage Mappings](stage-mappings.md) Automatic stage links across workflows for parent–child document relationships. [Read more →](stage-mappings.md) Click any node in the diagram above to see a summary and a link to the detailed page. --- ## Workflow Actions URL: https://documentation.skillsworkflow.com/docs/administration/workflows/action-types Summary: Reference table of the action types a workflow transition can run, and what each one does. Property Description CreateVersion text Assign text RequestConfirmation text SendEmail text SendToSap text CreateEstimate text FileUpload text Returned text AutoAssignResponsible text CompleteState text RequestMotive text RequestReference text Buy text Invoice text Request text ApproveOnSap text RejectOnSap text ActivateDocument text SendApproveOnSap text ApproveProductionOnSap text CancelOnSap text Canceled text RequestMotiveWithRequestedDate text RequestComment text RequestFlaggedAssignment text RequestClientUserFields text SendToExternal text ChangeEstimateExternalStatusTo text ChangeDeliverableExternalStatusTo text ActivateOnSap text RequestUserFields text RequestUserFields text ChangeDeliverableOrEstimateExternalStatusTo text ApproveItems text SynchronizeEstimateStageAndHistory text CreateEstimateVersion text CreatePlannedHoursFromEstimateItemDetails text DisapproveItems text Block text Unblock text ResetUserFields text CreatePlannedCostsFromEstimateItemDetails text ChangeClassification text RequiredAssign text ChangeDependentTaskStatusTo text ToIntegrate text DeletePlannedHoursFromEstimateItemDetails text AssignAdminResponsible text SyncApprovalStatus text ChangeEndDateToCurrentDay text ChangeChildTaskStage text DeletePlannedCostsFromEstimateItemDetails text UpdateProjectAssignments text CreatePlannedDeliverables text AddHoursToTimesheet text ChangeJobsStage text ChangeProjectStage text SendToExternalKeepOnError text ChangeRelatedEstimateStage text ChangeRelatedQuoteStatus text Credit text CloseProjectEstimates text EstimateMerge text IncreaseVersionDigit text DecreaseVersionDigit text CopyTeamFromRequest text CopyTeamFromParent text CreateJobsFromEstimateDeliverableQuantity text CreateTasksFromJobType text AssignTeamFromClientMarkets text ChangePurchaseOrderStage text CopyFromTeamToTeam text InvoiceJob text UpdateParentStage text MoveFromTeamToTeam text ChangeProjectsStage text ChangeEstimatesStage text RemoveTeam text UnlinkRequest text CopyTeamToFinancialCreatedDocuments text BlockChildren text UnblockChildren text CopyTeamToCreatedPurchaseOrders text ChildrenStageIn text SetChildrenStage text ChangeBillStage text SetParentStage text CreateEstimatesFromRequest text AssignTeamFromClientBrands text ChangeDocumentsStage text BlockDocuments text UnblockDocuments text AssignTeam text CustomTableWrite text UpdateUserFields text UpdateFields text EstimateUnmerge text Automation text UpdateFieldsValues text CopyFromTeamToTeamByQuery text AssignDepartmentTeam text AssignJobTypeTeam text AssignCreatedByTeam text AssignCommercialClientProjectManagerTeam text ExceedsBudget text CreatePlannedHoursDeliverableFromEstimateItemDetails text DeletePlannedHoursDeliverableFromEstimateItemDetails text DeleteDailyWorkloads text --- ## Workflows URL: https://documentation.skillsworkflow.com/docs/administration/importing-data/workflows Summary: Importing workflow definitions into Skills Workflow. Workflows # Build and extend --- ## Actions URL: https://documentation.skillsworkflow.com/docs/build-and-extend/automations/actions-reference Summary: This section describes the action types available in an Automation Workflow. This section describes the action types available in an Automation Workflow. Browse them by category below — each card jumps to that action's full reference, with its configuration, JSON template and examples. ## Flow control & structure Shape how the automation runs: start, finish, branch, loop, wait, and compose workflows. ### Start The Start action must be the first action set in the Automation Workflow. Without this action, the Automation Workflow will not be saved nor started, since this is the action that indicates that the workflow should begin. When this action is triggered, the payload will be loaded into the `"{{['#HttpRequest']$.Body}}"`. #### Configurations To configure this action, the fields required to be filled are: * actionType - Set as "Start" * name * next ```json title="Template" { "actionType": "Start", "name": "Starting", "next": "GetJobBrief" }, ``` #### Template Description * actionType – The type of action that will be triggered * name - The name of the action * next - The action that will be triggered after the current action been completed ### Result The Result action is the action responsible to finish the Automation Workflow. Once the Result action is triggered, it will end the automation workflow. It is also possible to return a custom response, by managing the action httpResponse field. #### Configuration The default Result action does not require any additional field other than actionType and the name. To have a custom Response you must configure the httpResponse. * httpResponse * statusCode * headers * body ```json title="Template" { "actionType": "Result", "name": "Exit", "httpResponse": { "statusCode": 200, "headers": { "content-type": "application/json" }, "body": "{{['SendExpenseFile']}}" } }, ``` #### Template Description * actionType - The action type is Result * name - The action name is custom * httpResponse - Optional * statusCode - The value to be sent in the HttpResponse statusCode * headers - The headers to be sent in the HttpResponse headers * body - The body to be sent in the HttpResponse body --- ### Case Case action works as a validator. It allows you to choose the path to follow according to a comparison of values. #### Configuration There are fields required to be filled to have this action working properly: * actionType - Case * test - The value that will be evaluated * nextActions - The next actions include the value to be compared, and the path forward (action name) if the values that are compared are the same * Default - The default indicates the path forward if none of the actions has a match ```json title="Template" { "actionType": "Case", "name": "ExistsGetSharepointSiteUrl", "test": "{{['PreviousActionName']$.field}}", "nextActions": [ { "default": false, "value": "200", "name": "GetConfigFile" }, { "default": true, "value": "", "name": "Exit" } ] }, ``` #### Template Description * actionType - The action type is Case * name - The action name is custom * test - The value that will be evaluated. Usually, it is the result/value of a previous action * nextActions - It is possible to have more than 2 nextAction to evaluate the test * default - True/false field and it is mandatory to have one nextAction with the default set as true * value - The value that will be compared against the value that is being in the test field * name - The name of the action to be triggered --- ### Loop The Loop action allows you to trigger a Sub-Workflow. To do so, it is required 2 parameters to be filled: * body * subWorkflow #### Configuration To configure this action, there are parameters that can be set: * body This field is at the Action level and must be populated with the data that should be used in the subWorkflow * subWorkflows This field is at the Automation Workflow level and can be accessed from any Loop action subWorkflows are like the principal automation workflow, where it is required to have: * Start action * Result action * When the subWorkflows ends, the next action set up in the Loop action will be triggered ```json title="Template" { "name": "ImportUsers", "actions": [ { "actionType": "Start", "name": "Starting", "next": "SftpDownload" }, { "actionType": "SftpDownload", "name": "SftpDownload", "next": "ReadFileData", "ftpHostIp": "sftp.skillsworkflow.com", "ftpUsername": "*", "ftpPassword": "", "filePath": "/Users", "fileName": "Users.csv", "fileType": "Csv" }, { "actionType": "ReadFileData", "name": "ReadFileData", "next": "LoopFileData", "fileName": "{{['SftpDownload']}}" }, { "actionType": "Loop", "name": "LoopFileData", "next": "MoveSftpFileSuccess", "body": "{{['ReadFileData']}}", "subWorkflow": "ImportFileData" }, { "actionType": "SftpMoveTo", "name": "MoveSftpFileSuccess", "next": "ExitSftpSucess", "ftpHostIp": "sftp.skillsworkflow.com", "ftpUsername": "", "ftpPassword": "*", "filePath": "/Users", "toFilePath": "/Users/Success", "fileName": "{{['#ImportFile']}}", "fileType": "Csv", "hasHeaderRecord": false }, { "actionType": "Result", "name": "ExitSftpSucess", "httpResponse": { "statusCode": 200, "headers": {}, "body": "File moved to Success folder." } } ], "subWorkflow": [ { "name": "ImportFileData", "actions": [ { "actionType": "Start", "name": "Starting", "next": "ImportUser" }, { "actionType": "Rest", "name": "ImportUser", "next": "CheckUserCreated", "Method": "Post", "url": "https://integration-api-skills-dev-we.azurewebsites.net/api/users", "body": "{\"userName\":\"{{['#ImportFileData'].username}}\",\"name\":\"{{['#ImportFileData'].Name}}\",\"externalId\":\"{{['#ImportFileData'].externalId}}\",\"companyCode\":\"{{['#ImportFileData'].CompanyCode}}\",\"departmentExternalId\":\"{{['#ImportFileData'].departmentid}}\",\"mail\":\"{{['#ImportFileData'].email}}\",\"isActive\":true,\"hireDate\":\"{{['#ImportFileData'].hiredate}}\",\"ssoUserName\":\"{{['#ImportFileData'].ssoUsername}}\",\"ssoUserNameUpdatable\":true,\"expirationDate\":\"{{['#ImportFileData'].expirationDate}}\",\"requiredWeeklyHours\":\"{{['#ImportFileData'].weeklyRequiredHours}}\",\"externalNumberUpdatable\":true,\"externalNumber\":\"{{['#ImportFileData'].externalNumber}}\",\"phone\":\"{{['#ImportFileData'].workphone}}\",\"isActive\":\"{{['#ImportFileData'].isActive}}\"}", "bodyMediaType": "Json" }, { "actionType": "Result", "name": "ExitUserNotCreated", "httpResponse": { "statusCode": 200, "headers": {}, "body": "User {{['ImportUser'].Content.userName}} imported.." } } ] } ] } ``` #### Template Description * actionType - The action type is Loop * name - The action name is custom * next - The next action to be executed after the subWorkflow execution reach its Result action * body - The data to be available in the Loop action * subWorkflow - The set of actions (e.g. import a list of files) to be performed ### Reduce The Reduce action allows you to group data by one or more property names and perform an aggregation operation over another property. Supported operations are SUM, MIN, MAX, AVG, or NONE (returns the first value). #### Configuration To configure this action, the following parameters need to be set: - data - GroupBy - Operation - OperationResult ```json title='Template' { "actionType": "Reduce", "name": "SumGroupedBy", "next": "Exit", "data": "{{['smallDataSet']}}", "GroupBy": [ "prop1", "prop2" ], "Operation": "SUM", "OperationResult": "value", "InnerArrayStrategy": "FIRST" } ``` ```json title='Example DataSet' [ { "prop1": "A", "prop2": "X", "array": [ 0, 1 ], "value": 30 }, { "prop1": "A", "prop2": "Y", "array": [ 1, 2 ], "value": 70 }, { "prop1": "B", "prop2": "X", "array": [ 2, 3 ], "value": 110 } ] ``` #### Template Description - actionType - The action type is Reduce - name - The action name is custom - next - The next action to be executed - data - The dataset on which the operation will be performed - groupBy - List of property names to group the data by - operation - The aggregation operation to apply: - SUM – aggregate values by summing them - MIN – the minimal value in the group - MAX – the maximum value in the group - AVG – the average value in the group - NONE – the first value in the group - operationResult - The target property on which the operation is applied - innerArrayStrategy - The default strategy to use when Data contains nested arrays: - NONE - the operation returns the entire array (default) - MIN - the operation returns the minimum value in the array - MAX - the operation returns to the maximum value in the array - FIRST - the operation returns the first value in the array - LAST - the operation returns the last value in the array > Note: The InnerArrayStrategy parameter `MIN` and `MAX` will only handle numeric values, it will ignore null or other type of values. ### Await The **Await** action allows the workflow to pause execution for a given duration before proceeding. #### Configuration To configure this action, there is one required parameter that must be set: * **duration** – The time to wait. Supported formats: * **ms** → milliseconds (`500ms`) * **s** → seconds (`1s`, `30s`) * **m** → minutes (`1m`, `5m`) ```json title="Template" { "actionType": "Await", "name": "AwaitOneSecond", "next": "Exit", "duration": "1s" } ``` #### Template Description - actionType – The action type is Await - name – The action name is custom - next – The next action to be executed after the wait period - duration – The wait time before continuing (e.g., 500ms, 1s, 1m) ### ExecuteSubWorkflow ExecuteSubWorkFlow action allows you to run a SubWorkflow with a specific Payload. This Action receives a Return action Result from the SubWorkflow. #### Configuration To configure this action, there are parameters that can be set: * subWorkflows - The SubWorkflow Name that is intended to run * body(optional) - This field is at the Action level and can be populated with the data that should be used in the subWorkflow ```json title="Template" { "actionType": "ExecuteSubWorkflow", "name": "RunSubWorkflow", "next": "Exit", "body": "{\"data\":\"value\"}", "subWorkflow": "MySubWorkflow" }, ``` #### Template Description * actionType - The action type is ExecuteSubWorkflow * name - The action name is custom * next - The next action to be executed after the subWorkflow execution reach its Result action * body - The data to be available in the ExecuteSubWorkflow action * subWorkflow - The set of actions (e.g. import a list of files) to be performed ### ExecuteIntegrationWorkflow ExecuteIntegrationWorkflow action allows you to run a Workflow with a specific Payload. This Action invokes a Workflow and waits for the workflow to finish and returns the result. #### Configuration To configure this action, there are required parameters that need to be set: * body # optional * targetWorkflowId ```json title="Template" { "actionType": "ExecuteIntegrationWorkflow", "name": "ExecuteIntegrationWorkflow", "next": "Exit", "body": "{\"documentType\":\"Skill.Module.BusinessObjects.CommercialClient\"}", "targetWorkflowId": "152e8a13-ea4e-469d-be39-f8d4ad0dd919" }, ``` #### Template Description * actionType - The action type is ExecuteIntegrationWorkflow * name - The action name is custom * next - The next action to be executed * body - The data to be available in the ExecuteIntegrationWorkflow action * targetWorkflowId - The Id of the workflow Intended to run. ### EnqueueBackgroundWork Enqueue action allows you to run a Workflow with a specific Payload. This Action invokes a Workflow and continues, it does not wait for the workflow to finish. #### Configuration To configure this action, there are parameters that can be set: * targetWorkflowId - The Workflow Id that is intended to run * body(optional) - This field is at the Action level and can be populated with the data that should be used in the subWorkflow. The body must be JSON. * sessionId (optional) - 60 Characters Maximum. When set will execute synchronously the workflow. In other words, it will wait for the previous to finish before starting the next one. * ExecuteOnUtc (Optional) - DateTime (YYYY-MM-ddTHH:mm:ss) Schedules execution for specific date and time. * Wait (Optional) - TimeSpan (dd:HH:mm:ss) Countdown Timer to execution. ```json title="Template" { "actionType": "EnqueueBackgroundWork", "name": "RunWorkflow", "next": "Exit", "targetWorkflowId": "0243dbd0-8c4b-4af1-a8fc-a26ae2ffa3e6", "body": "{\"documentType\":\"Skill.Module.BusinessObjects.CommercialClient\"}", "sessionId": "MySessionId", "executeOnUtc": "2024-09-18T18:30", "wait": "00:00:30" }, ``` #### Template Description * actionType - The action type is Enqueue * name - The action name is custom * next - The next action to be executed after the subWorkflow execution reach its Result action * body - The data to be available in the ExecuteSubWorkflow action * targetWorkflowId - The Id of the workflow Intended to run. * sessionId - The Id of the session so that it can execute synchronously. ### ClearContext ClearContext Action allows to remove unused Context created properties that are not really necessary anymore. User can clear all properties or select a list of properties to be removed. #### Configuration To configure this action, there are required parameters that need to be set: * listValues * clearAll # optional ```json title="Template" { "actionType": "ClearContext", "name": "ClearContext", "listValues": [ "property", "property1" ], "clearAll": false, "next": "Exit" }, ``` #### Template Description * actionType - The action type is ClearContext * name - The action name is custom * next - The next action to be executed * listValues - List of properties to bem removed. #Optional * clearAll - Flag to remove all properties #Defaults to false ## Integration & authentication Connect to external systems and obtain the tokens needed to reach them. ### Rest The Rest action allows doing Rest calls by setting in the Method parameter: * GET * POST * PUT * PATCH * DELETE #### Configuration To configure this action, the fields available are: * actionType - Rest * Method - GET/POST/PUT/PATCH/DELETE * bodyMediaType - Json/Raw/UrlEncodedFormData/MultipartFormData/File * url * body * requestHeaders - Key-Value array - `[{"name": "","value": ""}]` * bodyFormData * IsApiCall - Default False * EnsureSuccessStatusCode - Default False * responseHeaders - Array - `["date","x-api-version"]` ```json title="Template" { "actionType": "Rest", "name": "", "next": "", "Method": "GET/POST/PUT/PATCH/DELETE", "bodyMediaType": "Json/Raw/UrlEncodedFormData/MultipartFormData/File", "url": "", "body": "", "isApiCall": true, "ensureSuccessStatusCode": false, "requestHeaders": [ { "name": "", "value": "" } ], "bodyFormData": [], "responseHeaders": [] }, ``` #### Template Description * actionType – The actionType must be Rest for Rest actions * name - The name of the action * next - The action that will be triggered after the current action been completed * Method - Should be set according to the method to be applied * url - The URL to be called * isApiCall - If set, will append tenant Api Authority to request and add authentication Headers. Defaults to `true` * ensureSuccessStatusCode - If set, ensures that the response is a success Status Code (200 - 299). If not will throw an error and stop execution. Defaults to `False` * responseHeaders - If set, returns the response will bring the headers values for the keys defined. * bodyMediaType - Allows you to manage the Request headers and body. * Please see on the tabs below the bodyMediaType available: By setting the bodyMediaType as Json, it will automatically assume: * Body Media Type - "Json" * Content-Type - Set by default as "application/json" * Body - The request body should be set in JSON format and escaped ```json title="JSON" { "bodyMediaType": "Json", "body": "{\"parameter\":\"value\"}" } ``` By setting the bodyMediaType as Raw: * Body Media Type - "Raw" * Content-Type - It is required to set it manually by passing the requestHeaders * Request Headers - Use this field to manually set the request headers ```json title="Raw" { "bodyMediaType": "Raw", "body": "{\"parameter\":\"value\"}", "requestHeaders": [ { "name": "Content-Type", "value": "application/json-patch+json" }, { "name": "Authorization", "value": "Bearer {Token}" } ] }, ``` By setting the bodyMediaType as UrlEncodedFormData: * Content-Type - Set by default as "application/x-www-form-urlencoded" * bodyFormData - The request body should be sent in the bodyFormData parameter as an Array of Key - Values: `[{"key":"value"}]` ```json title="Url Encoded FormData" { "bodyMediaType": "UrlEncodedFormData", "bodyFormData": [ { "key": "grant_type", "value": "client_credentials" }, { "key": "client_id", "value": "fb3ccf6c-b672-45af-8389-51bfba06" }, { "key": "client_secret", "value": "5eKItuYeV3iZ1mxY8ktNWYY1bbKOgTO+POIR123/g=" } ] }, ``` By setting the bodyMediaType as File: * The file action allows you to add to the Content a StreamContent * The file's content will be sent as a sequence of bytes * Body - The body parameter must contain the file content * You can combine the Download action to obtain a file content from any URL ```json json title="File" [ { "actionType": "Download", "name": "DownloadFile", "next": "UploadFile", "url": "{{['GetProjectFile']$.Content.Uri}}" }, { "actionType": "Rest", "name": "UploadFile", "next": "Exit", "Method": "Post", "url": "https://skillsworkflow.com/sites/Coca-Cola/_api/UploadFile?name=Summer Campaign 2019", "body": "{{['DownloadFile']$.Content}}", "bodyMediaType": "File", "RequestHeaders": [ { "name": "Accept", "value": "application/json; odata=verbose" }, { "name": "Authorization", "value": "Bearer {Token}" } ] } ] ``` --- ### Sftp There are actions available to do actions related to SFTP: * SftpListFiles - Returns a list of files * SftpDownload - Download files * SftpUpload - Upload files * SftpMoveTo - Move files between folders #### Configuration There are configurations that need to be applied in the automation workflow in order to perform the actions properly. Please check the template description to know which parameters must be sent for each action. ```json title="Template" { "actionType": "SftpListFiles" or "SftpDownload" or "SftpUpload" or "SftpMoveTo", "name": "SftpListFiles", "next": "Exit", "ftpHostIp": "sftp.skillsworkflow.com", "ftpUsername": "SkillsWorkflow", "ftpPassword": "*", "ftpPrivateKeyFile": "PrivateKeyFile" "ftpPath": "", "ftpToPath": "", "filePath": "", "fileNameContains": "", "fileNameEndsWith": "", "fileName": "", "fileType": "Csv" }, ``` #### Template Description ```json title="Sftp List Files" { "actionType": "SftpListFiles", "name": "SftpListFiles", "next": "Loop", "ftpHostIp": "sftp.skillsworkflow.com", "ftpUsername": "SkillsWorkflow.Sftp.QA", "ftpPassword": "", "filePath": "/path", "fileNameContains": "", "fileNameEndsWith": "" }, ``` * actionType – The action type must be one of the following: SftpListFiles, * name - The name of the action * next - The action that will be triggered after the current action been completed * ftpHostIp – The host to be connected (ex: IP address or URL) * ftpUsername – The username that will be used to connect to the SFTP * ftpPassword – The user's password that will be used to connect to the SFTP * ftpPath - It is used to identify the directory where the file should be searched * fileNameContains – The action will filter the list of files by only showing the files that contain this parameter value * fileNameEndsWith – The action will filter the list of files by only showing the files that end with this parameter value ```json title="Sftp Download" { "actionType": "SftpDownload", "name": "SftpDownload", "next": "ReadFileData", "ftpHostIp": "sftp.skillsworkflow.com", "ftpUsername": "SkillsWorkflow.Sftp.QA", "ftpPassword": "", "ftpPath": "/path", "fileName": "{{['#ImportFile']}}" }, ``` * actionType – The action type must be one of the following: SftpDownload, * name - The name of the action * next - The action that will be triggered after the current action been completed * ftpHostIp – The host to be connected (ex: IP address or URL) * ftpUsername – The username that will be used to connect to the SFTP * ftpPassword – The user's password that will be used to connect to the SFTP * ftpPath - It is used to identify in which directory is the file * fileName - The file name that will be downloaded ```json title="Sftp Upload" { "actionType": "SftpUpload", "name": "SftpUpload", "next": "Exit", "ftpHostIp": "sftp.skillsworkflow.com", "ftpUsername": "SkillsWorkflow.Sftp.QA", "ftpPassword": "", "ftpPath": "/path", "filePath": "C:\\TempFolder\test.png", "fileName": "NewFilename.csv" }, ``` * actionType – The action type must be one of the following: SftpUpload * name - The name of the action * next - The action that will be triggered after the current action been completed * ftpHostIp – The host to be connected (ex: IP address or URL) * ftpUsername – The username that will be used to connect to the SFTP * ftpPassword – The user's password that will be used to connect to the SFTP * ftpPath - It is used to identify the directory where the file should be placed * filePath * It is used to identify the full path of the file in case it is in a temp folder (Download action result) * The value must have the whole path including the filename and extension * e.g. "C:\Folder\test.png" * fileName - The name that the file will have when uploaded into the SFTP including the file extension ```json title="Sftp Move To" { "actionType": "SftpMoveTo", "name": "MoveSftpFileSuccess", "next": "Exit", "ftpHostIp": "sftp.skillsworkflow.com", "ftpUsername": "SkillsWorkflow.Sftp.QA", "ftpPassword": "*", "ftpPath": "/path", "ftpToPath": "/toPath", "fileName": "{{['#ImportFile']}}" }, ``` * actionType – The action type must be one of the following: SftpMoveTo * name - The name of the action * next - The action that will be triggered after the current action been completed * ftpHostIp – The host to be connected (ex: IP address or URL) * ftpUsername – The username that will be used to connect to the SFTP * ftpPassword – The user's password that will be used to connect to the SFTP * ftpPath - It is used to identify the origin directory * ftpToPath - It is used to identify the destination directory where the file should be placed * fileName- The file name that will be moved between paths --- ### OAuth2Authentication Creates an OAuth2 Authentication based on Authorization Code Flow (defined in [OAuth 2.0 RFC 6749, section 4.1](https://tools.ietf.org/html/rfc6749#section-4.1)) Because regular web apps are server-side apps where the source code is not publicly exposed, they can use the Authorization Code Flow, which exchanges an Authorization Code for a token. Your app must be server-side because during this exchange, you must also pass along your application's Client Secret, which must always be kept secure, and you will have to store it in your client. #### Configuration To configure this action, there is a required parameter that need to be set: * OAuthClientId - Client Id * OAuthClientSecret - Client Password * OAuthBaseUrl - Authorization Server Url * OAuthScope - Application Filter to limit access * OAuthCallbackUrl - Return Address defined by provider in Authorized redirect URIs * OAuthUseStateVerification - If set, enables CSRF attacks Verification - Defaults to `False` * ```json title="Template" { "actionType": "OAuth2Authentication", "name": "GetToken", "next": "Exit", "oauthClientId": "MyClientId", "oauthClientSecret": "MyClientSecret", "oauthBaseUrl": "https://auth.Server/oauth", "oauthScope": "commercial", "oauthCallbackUrl": "http://127.0.0.1:4080/oauth/callback", "OauthUseStateVerification": true }, ``` #### Template Description * actionType - The action type is OAuth2Authentication * name - The action name is custom * next - The next action to be executed after the subWorkflow execution reach its Result action * oauthClientId - Client Id * oauthClientSecret - Client Secret * oauthBaseUrl - Auth Server base Url * oauthScope - Auth Scope * oauthCallbackUrl - Return Url * OauthUseStateVerification - CSRF attacks Verification #### Usage The result will be the configuration Keys value parameter: ```json title="Example Result" { "access_token": "c11e9a70ecfc6b9e2197ed42c4a3a68cc8e676ace0d4e28ae9e222fccd32456e", "expires_in": 14400, "refresh_token": "1160745-2655f33f8219b5b9f5fa50cabea4bade08d956d1485db3247bb323ca9951ea35", "token_type": "Bearer" } ``` ### AzureAdAuthentication AzureAdAuthentication action allows you to obtain an Authentication Token from the Azure Active Directory for a specified Resource using Credentials. #### Configuration The Azure Active Directory permissions assigned to the token are defined on the Azure Active Diretory application. There are configurations that need to be applied in the automation workflow in order to perform the actions properly. Please check the template description to know which parameters must be sent for each action. ```json title="Template" { "actionType": "AzureAdAuthentication", "name": "GetAzureAdToken", "next": "Exit", "tenantId": "s*******-3***-4***-a***-8***********", "clientId": "a*******-l***-5***-c***-1***********", "clientSecret": "*", "resource": "https://graph.microsoft.com" }, ``` #### Template Description * actionType – The action type is AzureAdAuthentication * name - The name of the action * next - The action that will be triggered after the current action been completed * tenantId - Microsoft Active Directory Tenant Id * clientId - Microsoft App Registration Id In Azure AD * clientSecret - Microsoft App Registration Secret * resource - The scope for authorization. Defaults to Microsoft Graph ### AzureAdCertificateAuthentication AzureAdCertificateAuthentication action allows you to obtain an Authentication Token from the Azure Active Directory for a specified Resource using a certificate. #### Configuration The Azure Active Directory permissions assigned to the token are defined on the Azure Active Diretory application. There are configurations that need to be applied in the automation workflow in order to perform the actions properly. Please check the template description to know which parameters must be sent for each action. ```json title="Template" { "actionType": "AzureAdAuthentication", "name": "GetAzureAdToken", "next": "Exit", "tenantId": "s*******-3***-4***-a***-8***********", "clientId": "3*******-1***-4***-8***-e***********", "CertificatePfx": "file.pfx", "CertificatePfxPassword": "MyfilePfxPassword", "resource": "https://graph.microsoft.com" }, ``` #### Template Description * actionType – The action type is AzureAdAuthentication * name - The name of the action * next - The action that will be triggered after the current action been completed * tenantId - Microsoft Active Directory Tenant Id * clientId - Microsoft App Registration Id In Azure AD * CertificatePfx - name of the pfx certificate to use. * CertificatePfxPassword - password for the pfx certificate. * resource - The scope for authorization. Defaults to Microsoft Graph ## Data & mapping Reshape, validate, query, and store data as it moves between actions. ### Map Map action allows you to Map previous actions Result to a property List of key/values. #### Configuration To do so it is required a parameter to be filled: * values - The mapped values will be available on the Map action result (Content) ```json title="Template" { "actionType": "Map", "name": "Map", "next": "Exit", "values": { "SubJobs": "{{['GetCompanies']$.Content[:1].SubJobs | ToJson}}", "Tasks": "{{['GetCompanies']$.Content[:1].Tasks | ToJson}}" } }, ``` ### MapFromObject MapfromObject allows to Map form names to properties. Passing a object Template with the mapped values from body will generate a new json object similar to data but with the values mapped by name from body. #### Configuration To configure this action, there are some required parameters that need to be set: * Data - Data Template with values as the body property names. * Body - The body with the content. ```json title="Template" { "actionType": "MapFromObject", "name": "MapFromObject", "next": "Exit", "data": "{\"name\":\"firstName\",\"years\":\"age\"}", "body": "{\"firstName\":\"John\",\"lastName\":\"Doe\",\"age\":\"30\"}" }, ``` #### Template Description * actionType - The action type is Enqueue * name - The action name is custom * next - The next action to be executed after the subWorkflow execution reach its Result action * data - The Template Data from witch to map property name * body - The body payload with data to fetch #### Usage The result will be in Data format with the values replaced from Body: ```json title="Example" { "name": "John", "years": "30" } ``` ### Merge Merge action allows you to Merge a Json Result from a previous to a property List of key/values. This Action allows to update properties from the Json Body. #### Configuration To do so it is required a parameter to be filled: * Payload - A Json Body * values - The mapped values will be available on the Merge action result (Content) ```json title="Template" { "actionType": "Merge", "name": "Merge", "next": "Exit", "payload": "{\"User\": \"string\",\"DocumentType\": \"string\", \"DocumentOid\": \"string\", \"AssignmentType\": \"string\", \"Workload\": 0, \"Priority\": 0}", "values": { "DocumentType": "{{['GetDocumentTypes']$.Content[:1].DocumentType | ToJson}}", "AssignmentType": "{{['GetAssignments']$.Content[:1].AssignmentType | ToJson}}" } }, ``` ### XmlMap XmlMap action allows you to parse a XML string to a property List of key/values using XPath. #### Configuration To configure this action, there are some required parameters that need to be set: * xmldata - A Xml String representing a Xml Document * Values - The mapped values will be available on the Map action result (Content) ```json title="Template" { "actionType": "XmlMap", "name": "XmlMap", "next": "Exit", "xmldata": "", "namespaces": { "cac": "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2", "cbc": "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2", "ubl": "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" }, "values": { "Id": "/cbc:ID", "AccountingSupplierName": "/cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc:Name", "StreetName": "/cac:AccountingSupplierParty/cac:Party/cac:PostalAddress/cbc:StreetName", "PostalCode": "/cac:AccountingCustomerParty/cac:Party/cac:PostalAddress/cbc:PostalZone", "Name": "/sender/name", "VatNumber": "/sender/id", "Address": "/sender/addressInformation/address", "City": "/sender/addressInformation/city" } }, ``` #### Template Description * actionType - The action type is Enqueue * name - The action name is custom * next - The next action to be executed after the subWorkflow execution reach its Result action * namespaces - Xml Namespaces used on Xml Document * xmlData - A Xml String representing a Xml Document * Values - The mapped values will be available on the Map action result (Content) ### ConvertFromJsonDataTable Allows to convert JSON between formats. It converts from the "DataTable" format to standard format. #### Configuration To configure this action, there is a required parameter that need to be set: * columns - Array With Column Definition `[{"name":"Timestamp","type":"string"},{"name":"Timestamp","type":"datetime"}]` * rows - Array With row values `["SkillsWorkflow","2023-05-02T00:00:00Z"]` ```json title="Template" { "actionType": "ConvertFromJsonDataTable", "name": "ConvertFromJsonDatatable", "next": "Exit", "columns": "{{['GetAppInsightsData'].Content.tables[0].columns}}", "rows": "{{['GetAppInsightsData'].Content.tables[0].rows}}" }, ``` #### Template Description * actionType - The action type is ConvertFromJsonDataTable * name - The action name is custom * next - The next action to be executed after the subWorkflow execution reach its Result action * columns - Array With Column Definition * rows - Array With row values #### Usage ```json title="Column Definition Available Types" [ "bool", "datetime", "dynamic", "guid", "int", "long", "real", "string", "decimal" ] ``` The original JSON: ```json title="DataTable Json" { "tables": [ { "name": "PrimaryResult", "columns": [ { "name": "Timestamp", "type": "datetime" }, { "name": "Id", "type": "string" }, { "name": "Tenant", "type": "string" }, { "name": "WorkspaceId", "type": "string" }, { "name": "Count", "type": "long" } ], "rows": [ [ "2023-05-02T00:00:00Z", "2023-05-02_Zas_1fabe874-e561-4b9e-86a5-4183234e0af6", "hogarth", "1fabe874-e561-4b9e-86a5-4183234e0af6", 9 ] ] } ] } ``` The result will be the transformed JSON: ```json title="Standard Json" { "Timestamp": "2023-05-02T00: 00: 00+00: 00", "Id": "2023-05-02_Zas_1fabe874-e561-4b9e-86a5-4183234e0af6", "Tenant": "Test", "WorkspaceId": "1fabe874-e561-4b9e-86a5-4183234e0af6", "Count": 9 } ``` ### JsonValidation Validate Required fields on a specific json payload. A list of properties is verified for missing, null or empty. In this case the action will return a list of errors and will exit on ExitOnError. #### Configuration To configure this action, there are required parameters that need to be set: * payload * requiredProperties * next * nextOnError ```json title="Template" { "actionType": "ValidateJson", "name": "ValidateJson", "payload": "{{['Payload']}}", "requiredProperties": [ "name", "company", "" ], "next": "Exit", "nextOnError": "ExitOnError" }, ``` #### Template Description * payload - json payload to verify * requiredProperties - List of property names to verify * next - next Action in case everything is verified * nextOnError - Next Action if any of the required properties is missing or is null ### SetParameter SetParameter creates parameter on the context with the value as result (variable). This parameter can be used globally as it is stored in the parent context. #### Configuration ```json title="Template" { "actionType": "SetParameter", "name": "MyParameter", "next": "Exit", "parameterName": "MyParameter", "value": "{{['#HttpRequest'].Host}}" }, ``` #### Template Description * actionType - The action type is Enqueue * name - The action name is custom * next - The next action to be executed after the subWorkflow execution reach its Result action * parameterName - The Name of the parameter. * value - Value of the parameter. #### Usage The list can be used calling the context parameter by name: `{{['MyParameter']}}` ### ConfigurationKeys ConfigurationKeys allows to retrieve a Skills Workflow Configuration Key and store the value as a parameter. #### Configuration To configure this action, there is a required parameter that need to be set: * value - Key name of the configuration key ```json title="Template" { "actionType": "ConfigurationKeys", "name": "GetConfigurationKeys", "next": "Exit", "value": "MyServerConfiguration" }, ``` #### Template Description * actionType - The action type is ConfigurationKeys * name - The action name is custom * next - The next action to be executed after the subWorkflow execution reach its Result action * value - Key name of the configuration key #### Usage The result will be the configuration Keys value parameter: ```json title="Template" { "TenantId": "d*******-3***-4***-a***-8***********", "ClientId": "3*******-1***-4***-8***-e***********", "ClientSecret": "y*******.f****~5*******.6**.n*****", "apiUrl": "h****://g*****.c**/S*************/M**********.g**" }, ``` ### AnalyticsNamedQuery AnalyticsNamedQuery action allows to run a Named Query on the Analytics Service. #### Configuration To configure this action, there are required parameters that need to be set: * body * NamedQuery ```json title="Template" { "actionType": "AnalyticsNamedQuery", "name": "AnalyticsNamedQuery", "next": "Exit", "body": "{\"documentType\":\"Skill.Module.BusinessObjects.CommercialClient\"}", "namedQuery": "Example - Named Query" }, ``` #### Template Description * actionType - The action type is AnalyticsNamedQuery * name - The action name is custom * next - The next action to be executed * body - The Query Parameters to be available * NamedQuery - The name of the Query. ## Files & documents Move files and produce structured documents from workflow data. ### Download Download action allows you to download the content of a file from a specific URL. #### Configurations To do so it is required a parameter to be filled: * url - The URL to download the file ```json title="Template" { "actionType": "Download", "name": "DownloadFile", "next": "UploadFile", "url": "{{['GetProjectFile']$.Content.Uri}}" }, ``` #### Template Description * actionType – The action type is Download * name - The name of the action * next - The action that will be triggered after the current action been completed * url - The URL to download the file ### Csv The CreateCsv action allows you to export data as a CSV file. To do so, it is required 2 parameters to be filled: * Data * DataColumns #### Configuration To configure this action, there are parameters that can be set: * Data This field should be populated with a data array "Data" field usually comes from the previous action result * i.e. the Automation Workflow has an action to get the data from the Execute Global Query * DataColumns This field should contain a list of Headers to be considered from the action with the data This field works as a filter to select which columns should be populated into the .CSV file * Delimiter The delimiter that will be used to separate the data and dataColumns * HasHeaderRecord True/false field to make the header appear on the first row when exporting the .CSV * Quote If necessary, you can set the quote that should be used to split the columns values ```json title="Template" [ { "actionType": "Start", "name": "Starting", "next": "GetExpenseFileData" }, { "actionType": "Rest", "name": "GetExpenseFileData", "next": "CreateCsv", "Method": "POST", "url": "https://apiv2-demo-dev-we.skillsworkflow.com/api/analytics/globalQuery/Expense - Export/execute", "body": "{}", "bodyMediaType": "Json" }, { "actionType": "CreateCsv", "name": "CreateCsv", "next": "SendExpenseFile", "hasHeaderRecord": false, "delimiter": ",", "quote": "\"", "data": "{{['GetExpenseFileData'].Content.Data}}", "dataColumns": [ "CompanyCode", "SentDate", "SentTime", "ExpenseSheetEmission", "Employee", "CostCenter", "CPF", "TotalValue", "TotalCashAdvance", "Filial", "Number", "ExpenseDate", "Client", "Job", "Motive", "ValueWithVat", "EncryptedString" ] }, { "actionType": "Rest", "name": "SendExpenseFile", "next": "Exit", "Method": "Post", "url": "https://e09905cd.ngrok.io/WS_DataTransfer.asmx?wsdl", "body": " {\"IdCompania\":\"4\", \"IDCategora\":\"6\", \"IDSubcategoria\":\"143\",\"Descripcion\":\"Skills Workflow test3\", \"solicitanteEmail\":\"bruno.moscao@wmccann.com\"}[{\"nombre\":\"teste.xlsx\", \"contenido\":\"{{['CreateCsv']$|ToBase64}}\"}]", "bodyMediaType": "Raw", "requestHeaders": [ { "name": "Content-Type", "value": "text/xml" } ] }, { "actionType": "Result", "name": "Exit", "httpResponse": { "statusCode": 200, "headers": {}, "body": "{{['SendExpenseFile']}}" } } ] ``` #### Template Description * actionType - The action type is CreateCsv * name - The action name is custom * next - The next action * hasHeaderRecord - The field to indicate if when exporting the headers should be included * data - The data in JSON to be considered to be exported * dataColumns - The columns that should be exported * delimiter - The columns delimiter e.g. "," , "\t" , ";", etc * quote - The value of the column will be within the character set in the quote e.g. "\"" to make the column values between " --- ### CSVMap The CSVMap action converts CSV (Comma-Separated Values) data into a JSON array. This is useful when external APIs return responses as CSV files or strings that need to be processed as JSON objects. #### Configuration To configure this action, the following parameters need to be set: * **data** - The CSV string content to be parsed (can use interpolation e.g., `{{['csvResponse']}}`) * **namesInFirstRow** - Boolean indicating if the first row contains column headers. If false, columns are auto-named as Field1, Field2, etc. * **delimiter** (optional) - The delimiter character. Defaults to comma (,) * **selectColumns** (optional) - Array of column names to include in the output. Ignored when namesInFirstRow is false * **next** - The next action to be executed after CSV parsing is complete * **ignoreSaveToContext** (optional) - If true, result is not saved to context ```json title="Template" { "actionType": "CSVMap", "name": "MapCSV", "next": "Exit", "data": "{{['CSVData']}}", "delimiter": ";", "namesInFirstRow": true, "selectColumns": [ "Nome do funcionário", "ID do funcionário", "Entrada 1", "Saída 1" ] } ``` #### Template Description * **actionType** - The action type is CSVMap * **name** - The action name is custom * **next** - The next action to be executed after CSV parsing is complete * **data** - The CSV string content to parse (can reference previous action results) * **namesInFirstRow** - Boolean (required). If true, the first row contains column headers. If false, columns are auto-named as Field1, Field2, etc. * **delimiter** - Optional. The delimiter character for separating values (default: ","). Other common delimiters: "\t" (tab), ";" (semicolon) * **selectColumns** - Optional. Array of column names to filter and include in the result (only available when namesInFirstRow is true). Case-insensitive matching * **ignoreSaveToContext** - Optional. If true, result is not saved to context #### Output Format The CSVMap action converts CSV rows into a JSON array of objects. ##### With Headers (namesInFirstRow: true) Input CSV data: ```csv Name,Age,City John,30,NewYork Jane,25,London ``` Output: ```json title="Output" [ {"Name":"John","Age":"30","City":"NewYork"}, {"Name":"Jane","Age":"25","City":"London"} ] ``` ##### Without Headers (namesInFirstRow: false) When no headers are present, columns are automatically named as Field1, Field2, Field3, etc. Input CSV data: ```csv John,30,NewYork Jane,25,London ``` Output: ```json title="Output" [ {"Field1":"John","Field2":"30","Field3":"NewYork"}, {"Field1":"Jane","Field2":"25","Field3":"London"} ] ``` #### Usage Examples ##### Example 1: Header Row with Column Selection Input CSV data (semicolon-delimited): ```csv Nome do funcionário;ID do funcionário;Departamento;Entrada 1;Saída 1;Entrada 2;Saída 2 John Doe;12345;Engineering;09:00;12:00;13:00;18:00 Jane Smith;67890;Marketing;08:30;12:30;13:30;17:30 ``` Configuration: ```json title="Example" { "actionType": "CSVMap", "name": "ParseTimesheet", "next": "ProcessData", "data": "{{['DownloadFile']}}", "delimiter": ";", "namesInFirstRow": true, "selectColumns": [ "Nome do funcionário", "ID do funcionário", "Entrada 1", "Saída 1" ] } ``` Result (accessed via `{{['ParseTimesheet']$.Content}}`): ```json title="Output" [ { "Nome do funcionário": "John Doe", "ID do funcionário": "12345", "Entrada 1": "09:00", "Saída 1": "12:00" }, { "Nome do funcionário": "Jane Smith", "ID do funcionário": "67890", "Entrada 1": "08:30", "Saída 1": "12:30" } ] ``` ##### Example 2: Header Row with All Columns If `selectColumns` is not specified, all columns will be included: ```json title="Example" { "actionType": "CSVMap", "name": "ParseAllColumns", "next": "ProcessData", "data": "Name,Email,Department\nJohn Doe,john@example.com,Engineering\nJane Smith,jane@example.com,Marketing", "namesInFirstRow": true, "delimiter": "," } ``` Result: ```json title="Output" [ { "Name": "John Doe", "Email": "john@example.com", "Department": "Engineering" }, { "Name": "Jane Smith", "Email": "jane@example.com", "Department": "Marketing" } ] ``` ##### Example 3: Without Header Row (Auto-naming) When CSV data doesn't have headers, column names are automatically generated as Field1, Field2, Field3, etc. Input CSV data: ```csv John Doe,john@example.com,Engineering Jane Smith,jane@example.com,Marketing ``` Configuration: ```json title="Example" { "actionType": "CSVMap", "name": "ParseNoHeaders", "next": "ProcessData", "data": "{{['CSVData']}}", "namesInFirstRow": false, "delimiter": "," } ``` Result (auto-named columns): ```json title="Output" [ { "Field1": "John Doe", "Field2": "john@example.com", "Field3": "Engineering" }, { "Field1": "Jane Smith", "Field2": "jane@example.com", "Field3": "Marketing" } ] ``` #### Logging The action logs: * Number of records being processed * Selected columns (when column filter is applied) * Auto-generated column names (when no headers present) --- ### CreatePdfFromDocument CreatPdfFromDocument action allows you to download a pdf from a existing document using a pre-existing layout #### Configuration To do so it is required a parameter to be filled: * documentType - The type of the document to create a Pdf * documentId - The id of the document * layoutId - The Id of the layout to use to create Pdf ```json title="Template" { "actionType": "CreatePdfFromDocument", "name": "GetPdfFromDocument", "next": "SendEmail", "documentType": "Expense", "documentId": "8b0412b4-37bc-47c9-9269-fa570f1f1f60", "layoutId": "20" }, ``` #### Template Description * actionType – The action type is CreatePdfFromDocument * name - The name of the action * next - The action that will be triggered after the current action been completed * documentType - Type of Document. ex: "Expense", "Project", "Deliverable" * documentId - The Id of the desired Document * layoutId - The layout id used to create pdf ## Lists Create and update lists held in the workflow context. ### CreateList CreateList action allows to create a list (Array) of values stored as a parameter on the context. This parameter can be used globally as it is stored in the parent context. #### Configuration To configure this action, there are some required parameters that need to be set: * listName - The list name. * listValues - The mapped values will be available on the context parameter. Optional Parameters: * distinct - Set to 'true' the list will only store distinct values (remove duplicates). * ignoreEmpty - Set to 'true' the list will only store non empty values. ```json title="Template" { "actionType": "CreateList", "name": "CreateList", "next": "UpdateList", "listName": "Mylist", "listValues": [ "{{['#HttpRequest'].Host}}", "{{['#HttpRequest'].Body}}", "", "b", "b", "c" ], "distinct": true, "ignoreEmpty": true }, ``` #### Template Description * actionType - The action type is Enqueue * name - The action name is custom * next - The next action to be executed after the subWorkflow execution reach its Result action #### Usage The list can be used calling the context parameter by name: `{{['MyList']}}` ### AddToList AddToList action allows to update an existing list (Array) of values stored as a parameter on the context adding new values to the end. #### Configuration ```json title="Template" { "actionType": "AddToList", "name": "UpdateList", "next": "RemoveFromList", "listName": "Mylist", "listValues": [ "{{['#HttpRequest'].Method}}", "", "e", "e" ], "distinct": true, "ignoreEmpty": true }, ``` #### Template Description * actionType - The action type is Enqueue. * name - The action name is custom. * next - The next action to be executed after the subWorkflow execution reach its Result action. * listName - The Name of the list. * listValues - Mapped values to the list result. * distinct - optional parameter to remove duplicates. * ignoreValues - optional parameter to remove empty values. ### RemoveFromList RemoveFromList action allows to remove values from an existing list (Array) of values stored as a parameter on the context. #### Configuration ```json title="Template" { "actionType": "removeFromList", "name": "RemoveFromList", "next": "Exit", "listName": "Mylist", "RemoveValues": [ "{{['#HttpRequest'].Method}}", "b", "e" ] }, ``` #### Template Description * actionType - The action type is Enqueue. * name - The action name is custom. * next - The next action to be executed after the subWorkflow execution reach its Result action. * listName - The Name of the list. * removeValues - Values to be removed from list result. ## Messaging & templates Reach people and render content from templates. ### E-mail Email action allows you to send e-mails. #### Configurations To do so, it is required some parameters to be filled: * body - The e-mail's body * subject - The email's subject * fromDisplayName - The display name that will appear on the sender * toAddress - The email address to whom the email should be sent ```json title="Template" { "actionType": "Email", "name": "SendEmail", "next": "Exit", "body": "This body can also be HTML.", "subject": "This is the e-mail subject", "fromDisplayName": "Notification | Skills Workflow", "toAddress": "user@skillsworkflow.com", "attachments": [ "document.pdf" ] }, ``` #### Template Description * actionType – The action type is Email * name - The name of the action * next - The action that will be triggered after the current action been completed * body - The body that should be sent in the e-mail's body. It also supports HTML * subject - The email's subject * fromDisplayName - The display name that will appear on the sender * toAddress - The email address to whom the email should be sent * attachment - Name of the File to attach in email --- ### ApplyTemplate The `ApplyTemplate` action renders dynamic text or HTML using the [Liquid template language](https://shopify.github.io/liquid/). The action receives: - **body** – A JSON object containing the values available to the Liquid template. - **data** – The Liquid template to render. Liquid supports: - **Objects** to display values: `{{ variable }}` - **Tags** for conditions and loops: `{% if %}`, `{% for %}` - **Filters** to transform values: `{{ value | upcase }}` #### Configuration ```json { "actionType": "ApplyTemplate", "name": "BuildDocumentTypeMessage", "next": "Exit", "body": "{\"documentType\":\"Skill.Module.BusinessObjects.CommercialClient\"}", "data": "Document Type: {{ documentType }}" } ``` The rendered result is: ```html Document Type: Skill.Module.BusinessObjects.CommercialClient ``` #### Conditional content Use Liquid tags to render content conditionally. ```json { "actionType": "ApplyTemplate", "name": "BuildStatusMessage", "next": "Exit", "body": "{\"documentName\":\"Campaign Brief\",\"approved\":true}", "data": "{% if approved %}{{ documentName }} was approved.{% else %}{{ documentName }} is awaiting approval.{% endif %}" } ``` #### Iterating over arrays Use the `for` tag to iterate through arrays. ```json { "actionType": "ApplyTemplate", "name": "BuildUserList", "next": "Exit", "body": "{\"users\":[{\"name\":\"Adam\"},{\"name\":\"Maria\"}]}", "data": "{% for user in users %}{{ user.name }}{% endfor %}" } ``` The rendered result is: ```html Adam Maria ``` #### Using filters Filters transform values before they are rendered. ```liquid {{ documentName | upcase }} {{ userName | default: "Unknown user" }} {{ description | escape }} ``` Filters can be chained: ```liquid {{ userName | capitalize | prepend: "Hello " }} ``` #### Parameters | Parameter | Description | |-----------|-------------| | `actionType` | Must be `ApplyTemplate`. | | `name` | Unique action name. | | `next` | Next action to execute. | | `body` | JSON object whose properties are available inside the Liquid template. | | `data` | The Liquid template to render. | > **Note:** Since `body` and `data` are JSON strings inside the automation definition, remember to escape quotation marks (`\"`) where required. --- ## Alert URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/ui/ui-alert Summary: A sub namespace of UI, exclusive for alert operations --- # Alert A sub namespace of UI, exclusive for alert operations ```javascript //accessing to ui.alert methods SW.UI.Alert.{methodName} ``` --- ## clear #### Description This method can be used to clear a toastr that is being displayed. #### Method(s) ```js {3} 1 function clear(): void ``` #### Basic Usage ```javascript SW.UI.Alert.clear(), ``` --- ## error #### Description This method can be used to show a Error toastr in the window and also in the console. #### Method(s) ```js {3} 1 function error( 2 response: string | HttpErrorResponse, 3 params: { 4 documentName?: DocumentName, 5 userName?: string, 6 userId?: string, 7 onClick?: Function 8 } = {} 9 ): void ``` Parameter Type Required Defaults Description response string | HttpErrorResponse true The message to be displayed in the alert documentName DocumentName false Document name userName string false User's name userId string false User's id onClick Function false Function executed when toastr is clicked #### Basic Usage ```javascript SW.UI.Alert.error("Toast error"); ``` #### Response --- ## info #### Description This method can be used to show a Info toastr in the window and also in the console. #### Method(s) ```js {3} 1 function info(message: string, 2 params: { 3 documentName?: DocumentName, 4 userName?: string, 5 userId?: string, 6 onClick?: Function 7 } = {} 8 ): void ``` Parameter Type Required Defaults Description message string true The message to be displayed in the alert documentName DocumentName false Document name userName string false User's name userId string false User's id onClick Function false Function executed when toastr is clicked #### Basic Usage ```javascript SW.UI.Alert.info("Toast info"); ``` #### Response --- ## success #### Description This method can be used to show a Success toastr in the window and also in the console. #### Method(s) ```js {3} 1 function success( 2 message: string, 3 params: { 4 documentName?: DocumentName, 5 userName?: string, 6 userId?: string, 7 onClick?: Function 8 } = {} 9 ): void ``` Parameter Type Required Defaults Description message string true The message to be displayed in the alert documentName DocumentName false Document name userName string false User's name userId string false User's id onClick Function false Function executed when toastr is clicked #### Basic Usage ```javascript SW.UI.Alert.success("Toast success"); ``` #### Response --- ## warning #### Description This method can be used to show a Warning toastr ine the window and also in the console. #### Method(s) ```js {3} 1 function warning(message: string, 2 params: { 3 documentName?: DocumentName, 4 userName?: string, 5 userId?: string, 6 onClick?: Function, 7 timeOut?: number 8 } = { 9 timeOut: this.DEFAULT_TIMEOUT 10 } 11 ): void ``` Parameter Type Required Defaults Description message string true The message to be displayed in the alert documentName DocumentName false Document name userName string false User's name userId string false User's id onClick Function false Function executed when toastr is clicked timeOut number false 5500 Display time of the toastr #### Basic Usage ```javascript SW.UI.Alert.warning("User field is required"); ``` #### Response --- ## Allow Inline Editing URL: https://documentation.skillsworkflow.com/docs/build-and-extend/workspaces/panels/grid-inline-editing Summary: On this page you will find how to use inline editing. On this page you will find how to use inline editing. To use it, you need to turn on the allow inline editing button. When this button is enable the following properties will have the following values: - Allow Updating: true - mode: "cell" By default all the columns appear not editable. If you want to enable a column put the allowEditing with the value of true ## saveOptions A function used to save the userfields. For the document's fields, you don't need to use it. Make sure that the name of the field in the query is the same that appears in the PATCH endpoint. ### type Accepted Values: 'userfield' ```js {3} { saveOptions: { type: "userfield"; } } ``` dataType Indicates the type of data, each data type corresponds to a number. ```js {4} { saveOptions: { type: "userfield", dataType: 7 } } ``` fieldName To assign the name you want to save the field. if the name of the field doesn't match with the original name (the that exists in the database). ```js {5} { saveOptions: { type: "userfield", dataType: 7 fieldName: "ProjectComment" }, dataField: 'Comment', dataType: 'string', allowEditing: true } ``` --- ## Argument Axis URL: https://documentation.skillsworkflow.com/docs/build-and-extend/workspaces/panels/chart-argument-axis Summary: A property used to set chart's argument axis in a workspace. A property used to set chart's argument axis in a workspace. The argumentAxis object, configures the argument axis individually. By default, the argument axis will show just text, but by using the properties label, format, type and entity it can show a image. ```javascript { argumentAxis: { label: { format: { type: "image", entity: "user", mapping: { id: "Oid", name: "LoginName", hasImage: "HasImage" } } } } } ``` ### entity To choose which of the entities mentioned below will be represented. Accepted Values: 'client' | 'company' | 'user' ```javascript { entity: "user"; } ``` Required on data source: - Id - Name - HasImage ```javascript { entity: "client"; } ``` Required on data source: - Id - Name - HasImage ```javascript { entity: "company"; } ``` Required on data source: - Id - Name - HasImage #### mapping If the data source doesn't match the mapping to the default fields, it can be mapped by using the mapping property: ```javascript { entity: "user", format: { mapping: { id: "UserId", name: "UserName", hasImage: "UserHasImage" } } } ``` #### Properties defined in the chart configuration #### Chart argument axis UI --- ## Assignment URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/document/document-assignment Summary: A sub namespace of Document, exclusive for assignment operations --- A sub namespace of Document, exclusive for assignment operations --- ## update #### Description This method can be used to update an assignment field/s. #### Method(s) ```js {3} 1 declare function update( 2 assignmentId: string, 3 documentId: string, 4 documentType: string, 5 params: { newValuesModel?: any } = {} 6 ): Promise ``` Parameter Type Required Defaults Description assignmentId string true Assignment id documentId string true DocumentId id documentType string true Document type newValuesModel any false New values to update assignment #### Basic Usage ```javascript SW.Document.Assignment.update( "dd54bd31-376f-4fe7-b840-102016759b6b", "570f95fe-6b41-43a5-830f-cb644e6285e0", "Skill.Module.BusinessObjects.Deliverable", { newValuesModel: { User: newExecutorId } } ); ``` --- ## Automations URL: https://documentation.skillsworkflow.com/docs/build-and-extend/automations Summary: Automation Workflows run a chain of configured actions when an event fires, a webhook is called, or a schedule comes due — calling external systems, transforming data, sending mail and returning responses. An Automation Workflow runs a chain of configured actions without anyone pressing a button. Something starts it, an optional condition decides whether it should carry on, and the actions do the work: calling an external API, moving a file over SFTP, building a CSV, sending mail, or returning a response to whoever called. Every workflow has the same skeleton. It begins at a mandatory **Start** action and finishes at a **Result**, and each action in between names the one that follows it. That chain is the whole model, and it is what the builder draws. ## What starts a workflow Three things, covered in [How automations start](./triggers.md): | Source | Use it for | |---|---| | A system event | Reacting to work happening in Skills Workflow, such as a project being created. | | A webhook | Letting an external system call in, with the request body available to every action. | | A schedule | Running on a fixed cadence, such as an hourly sync. | ## Where to go next **New to automations?** [Build your first automation](./getting-started.md) walks from an empty screen to a working workflow that calls an external endpoint. **Building one now?** [Actions](./actions-reference.md) is the catalogue of every action type, with its required fields, JSON template and examples. [Workflow structure](./workflow-structure.md) covers the rules a workflow must satisfy before it will save. **Wiring data between actions?** [Expressions](./expressions/index.md) covers the `{{ }}` syntax, the functions and pipe functions available, and JSONPath for reaching into results. **Want a working starting point?** [Recipes](./recipes/export-to-csv.md) are complete automations you can copy and adapt. ## Related articles - [Webhooks](../api/webhooks.md) - [Actions](./actions-reference.md) - [Expressions](./expressions/index.md) --- ## Branding URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/branding Summary: With this namespace, you can quickly provide methods to manipulate the tenant branding. # Branding With this namespace, you can quickly provide methods to manipulate the tenant branding. The namespace Branding provides to developers, methods to easily get and set a tenant branding. ```javascript //accessing to Branding methods SW.Branding.{methodName} ``` --- ## get #### Description This method can be used to get the tenant branding. #### Method(s) ```javascript 1 declare function get(): BrandingDto; ``` #### Basic Usage ```javascript SW.Branding.get(); ``` --- ## set #### Description This method can be used to set the tenant branding. #### Method(s) ```javascript 1 declare function set(brandingDto: BrandingDto): void; ``` Parameter Type Required Defaults Description url brandingDto true New branding to set #### Basic Usage ```javascript SW.Branding.set({ loginImage: { url: 'loginImageURL', style: 'width: 100px; heigth: 100px' } }); ``` --- ## Build your first automation URL: https://documentation.skillsworkflow.com/docs/build-and-extend/automations/getting-started Summary: This walkthrough takes you from an empty screen to a working automation. This walkthrough takes you from an empty screen to a working automation. We'll build a common one: **when a project is created, notify an external system**. By the end you'll recognise the shape every automation shares, and know how to wire actions together. An automation that fires on *project created*, calls an external endpoint with the new project's details, and returns a success response. Here's the chain we're aiming for — click any step to see what it does: ## Step 1: Open the Automation Workflows builder From **Customization → Automations**, choose **New workflow**. A new Automation Workflow always begins with two actions already in place — a `Start` and a `Result` — because both are mandatory. Everything you add goes *between* them. Give the workflow a name, for example `NotifyOnProjectCreated`. ## Step 2: Choose the event that triggers it Select the system event that should start the automation — in our case, a **project being created**. This is the automation's **Trigger**. The data carried by the trigger is always available through the `{{['#HttpRequest']}}` parameter. For a project-created event, the new project's fields arrive in `{{['#HttpRequest'].Body}}` — we'll use that in the next step. ## Step 3: Add your first action Add a `Rest` action between `Start` and `Result`, and name it `NotifyChannel`. Point `Start` at it by setting `Start`'s `next` to `NotifyChannel`, and point `NotifyChannel`'s `next` at the `Result` action. This is the core pattern: **each action names the next one via `next`**, forming the chain. ```json title="The NotifyChannel action" { "actionType": "Rest", "name": "NotifyChannel", "next": "Exit", "Method": "POST", "bodyMediaType": "Json", "url": "https://hooks.example.com/projects", "body": "{\"text\":\"New project created: {{['#HttpRequest'].Body.Name}}\"}", "isApiCall": false, "ensureSuccessStatusCode": true } ``` Notice `{{['#HttpRequest'].Body.Name}}` inside the body — that pulls the project's name straight from the trigger. Any earlier action's result can be referenced the same way, using `{{['ActionName']}}`. See [Writing expressions](./expressions/index.md) for the full syntax. ## Step 4: Confirm the Result The `Result` action returns the response the caller receives once the chain finishes. The default is fine for our case — a `200` with an empty JSON body. ```json title="The Result action" { "actionType": "Result", "name": "Exit", "httpResponse": { "statusCode": 200, "headers": { "content-type": "application/json" }, "body": "" } } ``` ## Step 5: Review the whole automation Put together, the three actions form one complete automation. This is exactly what gets saved: ```json title="NotifyOnProjectCreated" { "name": "NotifyOnProjectCreated", "actions": [ { "actionType": "Start", "name": "Start", "next": "NotifyChannel" }, { "actionType": "Rest", "name": "NotifyChannel", "next": "Exit", "Method": "POST", "bodyMediaType": "Json", "url": "https://hooks.example.com/projects", "body": "{\"text\":\"New project created: {{['#HttpRequest'].Body.Name}}\"}", "isApiCall": false, "ensureSuccessStatusCode": true }, { "actionType": "Result", "name": "Exit", "httpResponse": { "statusCode": 200, "headers": { "content-type": "application/json" }, "body": "" } } ] } ``` ## Step 6: Test and save Run the automation once to check each action's result inline, then save. From now on it fires automatically every time a project is created. Want it to run only for some projects? Add a **Condition** so the automation proceeds only when your filter is met — for example, only for projects above a certain budget. See the [Overview](./index.md) for where conditions sit in the flow. ## Where to go next - **[Actions](./actions-reference.md)** — every action type you can add to the chain, with templates and examples. - **[Expressions](./expressions/index.md)** — how actions share data, plus functions, pipe functions and JSONPath. - **[Workflow structure](./workflow-structure.md)** — the rules a workflow must satisfy before it saves, sub-workflows and error routing. - **[Recipes](./recipes/export-to-csv.md)** — complete, copy-paste automations for common scenarios. --- ## Buttons URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/ui/ui-buttons Summary: A sub namespace of UI, exclusive for buttons operations --- # Buttons A sub namespace of UI, exclusive for buttons operations ```javascript //accessing to ui.buttons methods SW.UI.Buttons.{methodName} ``` --- ## addCreateToSubHeader #### Description This method can be used to generate a create button in the sub-header. #### Method(s) ```javascript function addCreateToSubHeader(documentName: string, component: dxForm, params: { onClick?: (dashboardDocumentSaveObject: DashboardDocumentSaveObject) => boolean; components?: { description?: dxHtmlEditor; files?: FileSystemWidgetComponent; }; mappers?: { postModel?: ( postModel: PostModel, dashboardDocumentSaveObject: DashboardDocumentSaveObject, params: { isDraftModel: boolean } ) => PostModel; briefPostModel?: ( briefPostModel: BriefPostModel, dashboardDocumentSaveObject: DashboardDocumentSaveObject ) => BriefPostModel; }; postChangesOnFeed?: boolean; allowDraft?: boolean; icons?: { save?: { class?: string; tooltip?: string; }; draft?: { class?: string; tooltip?: string; }; }; } = { allowDraft: true, postChangesOnFeed: false } ): void ``` Parameter Type Required Defaults Description documentName string true Document name component dxForm true Form where it will be added the button descriptionComponent any true null onClick Function false On button click function callBack any true Callback function description dxHtmlEditor false Description box files FileSystemWidgetComponent false File upload component postModel PostModel false Post model for document creation dashboardDocumentSaveObject DashboardDocumentSaveObject false Object to save document isDraftModel boolean false If document is draft briefPostModel BriefPostModel false Brief post model dashboardDocumentSaveObject DashboardDocumentSaveObject false Object to save document postChangesOnFeed boolean false Flag to allow changes on feed allowDraft boolean false If document can be draft class string false Save button icon tooltip string false Save button tooltip class string false Draft button icon tooltip string false Draft button tooltip #### Basic Usage ```javascript SW.UI.Buttons.addCreateToSubHeader("project", e.component, { onClick: (postModel, dashboardDocumentSaveObject) => { postModel["Custom"] = { JobTypeId: postModel.Actions.Document.Project.ProjectNatureId }; return postModel; }, components: { description: SW.getComponent("description") } } ); ``` #### Response --- ## addSaveToSubHeader #### Description This method can be used to generate a save button in the sub-header. #### Method(s) ```javascript function addSaveToSubHeader(documentName: string, component: dxForm, params: { patchEndpoint?: string; onClick?: (currentDocument: Document, formComponent: dxForm, otherFields: any) => void; postChangesOnFeed?: boolean; icons?: { save?: { class?: string; tooltip?: string; }; }; } = { postChangesOnFeed: false } ): void ``` Parameter Type Required Defaults Description documentName string true Document name component dxForm true Form where it will be added the button patchEndpoint string false Endpoint for patch request onClick Function false On button click function postChangesOnFeed boolean false Flag to allow changes on feed class string false Button icon tooltip string false Button tooltip #### Basic Usage ```javascript SW.UI.Buttons.addSaveButtonToSubHeader("commercialclient", e.component, {postChangesOnFeed: true }); ``` #### Response --- ## addToSubHeader #### Description This method can be used to add buttons to the sub-header. #### Method(s) ```javascript 1 function addToSubHeader(component: DOMComponent, buttons: SubHeaderButton[]): void ``` Parameter Type Required Defaults Description component DOMComponent true Parent component where the buttons will be added buttons SubHeaderButton[] true An array of buttons #### Basic Usage ```javascript SW.UI.Buttons.addToSubHeader(e.component, buttons); ``` Buttons have the following structure #### Response --- ## setAllEnabled #### Description This method can be used to enable or disable buttons. #### Method(s) ```javascript 1 function setAllEnabled(value: boolean): void ``` Parameter Type Required Defaults Description value boolean true True to enbale and false to disable #### Basic Usage ```javascript SW.UI.Buttons.setAllEnabled(true) ``` --- ## Client URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/document/document-client Summary: A sub namespace of Document, exclusive for client operations --- Get Custom Fields Get Lookup Set Custom Fields Update --- A sub namespace of Document, exclusive for client operations --- The same methods that are presented in the Document Introduction but do not take the first param documentName, because you're already in a Client document [Get Custom Fields](./#getcustomfields) [Get Lookup](./#getlookup) [Set Custom Fields](./#setcustomfields) [Update](./#update) --- ## getImages #### Description This method can be used to get clients image url. #### Method(s) ```javascript 1 declare function getImages(ids: string[]): string[]; ``` Parameter Type Required Defaults Description ids string[] true Array of client ids #### Basic Usage ```javascript SW.Document.Client.getImages(["f6671567-67b2-430c-bf04-dc7a41e99395"]); ``` --- ## Client API URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/client-api Summary: The Client API is designed for creating and updating documents in Skills Workflow. ## Overview The Client API is designed for creating and updating documents in Skills Workflow. It’s not intended for bulk data extraction or reporting—use our Data API for that. ### Purpose The Client API is intended for interacting with and managing documents and entities within Skills Workflow. It allows for the creation, update, and manipulation of items within your workflow but is not suited for large-scale data extraction. ### Use Cases Integrate Skills Workflow into tools such as: - Project management systems: Asana, Trello, Monday, ZiFlow - Collaboration platforms: AirTable, Notion - Business systems: ERP systems, attendance tracking, and other external document workflows ### Key Limitations - Not for data extraction: Don’t rely on this API to pull large datasets; use the Data API for that purpose. - 30-second execution cap: Long-running calls will be terminated. For optimal performance, use filters or pagination (e.g., skip/take) on listing endpoints. - Rate limits may apply: High-frequency requests should be managed to avoid throttling. - Limited data interactions: This API focuses on document creation and updating, not extensive data querying or analysis. --- ## Getting Started ### Authentication Before calling any endpoint, you must obtain the following credentials from our Support team: - **App Key** (`X-AppId`) - **App Secret** (`X-AppSecret`) - **Tenant ID** (`X-AppTenant`) > These are provided by the support team upon request. Include them in each request via HTTP headers: ```http X-AppTenant: X-AppId: X-AppSecret: X-AppUser: # Optional, if user-scoped filtering is required Content-Type: application/json ``` ### Environments The API is available in four environments, depending on your subscription plan: - **Development** - **Test** - **UAT** - **Production** Each environment has its own base URL: ``` {{ApiUrl}}/api/v3/analytics ``` ### Postman Collection To facilitate testing of the available queries, we provide a Postman collection file with all endpoints configured. You can download it from the link below: [Download Postman Collection - Client API](/templates/client-api-postman-collention.json) After downloading, make sure to configure the variables `{{ApiUrl}}`, `{{TenantId}}`, `{{AppId}}`, `{{AppSecret}}`, and `{{UserId}}` according to the credentials you have been given. --- ### Rate Limits - **30-second cap** on every call—avoid timeouts by filtering or paging large result sets. - Listing endpoints support two query parameters: - `skip` (int): number of records to skip - `take` (int): maximum number of records to return --- ## Endpoints [Swagger](https://apiv2-demo-prod-we.skillsworkflow.com/swagger/index.html) --- ## Examples ### Creating a Document The `/api/posts` endpoint is the main way client integrations create documents in Skills Workflow. A single call can: - Create a new document (when `Actions.Document` is supplied) - Add a comment to a document's feed - Run a workflow stage transition on a document - Attach an initial Document Brief `DocumentId` does not select an existing document to update when `Actions.Document` is present — see the [Payload Reference](#payload-reference) below for how document creation and comment/transition-only calls differ. #### Request ```http POST https://apiv2-{{Tenant}}.skillsworkflow.com/api/posts ``` Include the standard [authentication headers](#authentication) and set `Content-Type: application/json`. #### Payload Reference These fields make up the common request envelope, regardless of which document type is being created: | Field | Type | Description | |---|---|---| | `DocumentId` | `guid` | ID of the document the post/comment/transition applies to. When `Actions.Document` is included, a new document of that type is always created and this field is ignored for that purpose — it can simply be omitted, as in the examples below. To add a comment or run a transition on an **existing** document without creating one, omit `Actions.Document` and set this to that document's ID instead. | | `DocumentTypeName` | `string` | The document type being created or updated — see [Supported Document Types](#supported-document-types) below. | | `Text` | `string` | Comment added to the document's feed. | | `Actions.Transition` | `object` | Optional. Runs a workflow stage transition on the document as part of the same call. | | `Actions.Transition.StatusId` | `guid` | ID of the workflow status/stage the document is in. | | `Actions.Transition.TransitionId` | `guid` | ID of the workflow transition to execute. | | `Actions.Document` | `object` | Optional. Present only when creating a new document (or, for Deliverable, updating one — see below). | | `Actions.Document.DocumentType` | `string` | Same value as `DocumentTypeName`. | | `Actions.Document.DocumentActionType` | `string` | Required whenever `Actions.Document` is present. Use `"Post"` to create a document. **Deliverable** is the only type that also supports `"Put"`, to update an existing Deliverable instead of creating one (using a `JobPutModel` object in place of `Job` — not covered in detail here). | | `Actions.Document.` | `object` | The document's own fields. The property name and shape depend on the document type — see [Supported Document Types](#supported-document-types) and the tabs below. | | `Actions.Document..DocumentBrief` | `object` | Optional, only for document types that support it (see below). Creates an initial Brief linked to the document — see [Document Brief](#document-brief) below. | Unlike the other fields above, `DocumentBrief` is nested **inside** the type-specific object (e.g. `Actions.Document.Project.DocumentBrief`), not as a sibling of it. #### Supported Document Types | `DocumentType` value | Nested property under `Actions.Document` | Supports `DocumentBrief`? | |---|---|---| | `Project` | `Project` | Yes | | `Deliverable` | `Job` (create) / `JobPutModel` (update) | Yes, create only | | `Contract` | `Contract` | Yes | | `Estimate` | `Estimate` | Yes | | `Expense` | `Expense` | Yes | | `ExpenseItem` | `ExpenseItem` | Yes | | `RateCard` | `RateCard` | No | | `PriceTable` | `PriceTable` | No | | `Request` | `Request` | Yes | | `Tender` | `Tender` | No | `Deliverable` is the only type where the nested property name doesn't match `DocumentType` — it's `Job`, not `Deliverable`. #### Examples by Document Type Each tab below shows a minimal creation payload and the fields table for that document type. Fields lists are not exhaustive — see [Swagger](#endpoints) for the full schema of each type. `Text` and `Actions.Transition` (shown in the **Project** tab) can be combined with any document type the same way. The example below creates a new **Project** document, adds a comment to its feed, and runs a workflow transition on it in the same call. ```json { "DocumentTypeName": "Project", "Text": "Comment to be added initially to the newly created project's feed.", "Actions": { "Transition": { "StatusId": "e8e4651f-f6e2-4053-918b-1fb25ac7b6f6", "TransitionId": "2a0f65ab-408c-4696-8454-757a444dea9e" }, "Document": { "DocumentType": "Project", "DocumentActionType": "Post", "Project": { "ClassificationId": "7d16465d-b535-44f1-822a-3ab449dab77b", "ClientId": "94177d4d-670b-47b9-a3ff-f05bb4deaf6e", "ContractId": "eee0c262-abbe-4ccf-9e44-a126402586bc", "CurrencyId": "12bb8ac2-1729-4be3-a587-0705c4888211", "BeginDateUtc": "2024-05-31T23:22:07.3520703Z", "EndDateUtc": "2024-12-01T00:22:07.3520703Z", "Investment": 0.0, "IsDraft": true, "ProductId": "8f77ad60-228d-4d07-a3f5-ff5ee2e64d8e", "ProjectNatureId": "c3d4e5f6-a7b8-49c0-8d1e-2f3a4b5c6d7e", "ProjectOwnerId": "d4e5f6a7-b8c9-4ad0-9e1f-3a4b5c6d7e8f", "AllowsTimesheet": true, "IsDeliverable": true, "DocumentBrief": { "DocumentTypeName": "Project", "Text": "" } } } } } ``` Fields under `Actions.Document.Project`: | Field | Type | Description | |---|---|---| | `ClassificationId` | `guid` | Project classification. | | `ClientId` | `guid` | Client the project belongs to. | | `ContractId` | `guid` | Associated contract. | | `CurrencyId` | `guid` | Currency used for the project's financials. | | `BeginDateUtc` | `datetime` | Project start date (UTC). | | `EndDateUtc` | `datetime` | Project end date (UTC). | | `Investment` | `number` | Planned investment amount. | | `IsDraft` | `boolean` | Whether the project is created as a draft. | | `ProductId` | `guid` | Associated product. | | `ProjectNatureId` | `guid` | Project nature/category. Use the empty GUID if not applicable. | | `ProjectOwnerId` | `guid` | Project owner (user). Use the empty GUID if not set. | | `AllowsTimesheet` | `boolean` | Whether timesheets can be logged against the project. | | `IsDeliverable` | `boolean` | Whether the project itself acts as a deliverable. | `CompanyId`, `ProjectManagerId`, `BusinessObjectTypeId`, and `IsActivated` are deliberately left out here — they have no effect when creating a Project (they only apply when updating one through the client update endpoints). There's also no `ProjectType` field: the server always derives it from whether `ContractId` is set, so any submitted value would be discarded. ```json { "DocumentTypeName": "Deliverable", "Actions": { "Document": { "DocumentType": "Deliverable", "DocumentActionType": "Post", "Job": { "Name": "New landing page copy", "ProjectId": "3d9c1b3a-1a2b-4c3d-9e0f-1a2b3c4d5e6f", "ClientId": "94177d4d-670b-47b9-a3ff-f05bb4deaf6e", "ProductId": "8f77ad60-228d-4d07-a3f5-ff5ee2e64d8e", "DepartmentId": "5b2e1f6a-3c4d-4e5f-8a9b-1c2d3e4f5a6b", "JobTypeId": "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d", "AgreedDateUtc": "2024-12-01T00:00:00Z", "IsDraft": true, "AllowsTimesheet": true, "IsDeliverable": true, "DocumentBrief": { "DocumentTypeName": "Deliverable", "Text": "" } } } } } ``` Fields under `Actions.Document.Job` (create): | Field | Type | Description | |---|---|---| | `Name` | `string` | Deliverable title. | | `ProjectId` | `guid` | Parent project. **Required** — the Deliverable can't be created without it, even as a draft. | | `ParentJobId` | `guid` | Optional parent Deliverable, for sub-deliverables. | | `ClientId` | `guid` | Client the Deliverable belongs to. | | `ProductId` | `guid` | Associated product. | | `ContractId` | `guid` | Associated contract. | | `DepartmentId` | `guid` | Owning department. | | `JobTypeId` | `guid` | Deliverable type. | | `JobClassificationId` | `guid` | Deliverable classification. | | `BusinessObjectTypeId` | `guid` | Business object type. | | `AgreedDateUtc` | `datetime` | Agreed delivery date (UTC). | | `IsDraft` | `boolean` | Whether the Deliverable is created as a draft. | | `WorkflowStateId` | `guid` | Initial workflow stage. | | `Priority` | `int` | Priority code. | | `AllowsTimesheet` | `boolean` | Whether timesheets can be logged against it. | | `IsDeliverable` | `boolean` | Whether this Deliverable counts as a deliverable in reporting (as opposed to an internal task). | | `MarketId` | `guid` | Associated market. | A few fields are accepted but have no effect on **creation**: `RequestedDateUtc` (always derived from `AgreedDateUtc`), and `WorkflowId`/`DocymentTypeId` (the workflow is always computed from `DepartmentId` + `JobTypeId`). If `ProductId` belongs to a different client than `ClientId`, the server silently drops it instead of erroring. Updating an existing Deliverable uses `DocumentActionType: "Put"` with a `JobPutModel` object (in place of `Job`) — a distinct model not covered in full here. ```json { "DocumentTypeName": "Contract", "Actions": { "Document": { "DocumentType": "Contract", "DocumentActionType": "Post", "Contract": { "Name": "Annual retainer 2025", "ClientId": "94177d4d-670b-47b9-a3ff-f05bb4deaf6e", "ProductId": "8f77ad60-228d-4d07-a3f5-ff5ee2e64d8e", "JobTypeId": "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d", "Value": 50000.0, "StartDateUtc": "2025-01-01T00:00:00Z", "EndDateUtc": "2025-12-31T00:00:00Z", "IsDraft": true, "DocumentBrief": { "DocumentTypeName": "Contract", "Text": "" } } } } } ``` Fields under `Actions.Document.Contract`: | Field | Type | Description | |---|---|---| | `Name` | `string` | Contract name. | | `ClientId` | `guid` | Client the contract belongs to. **Required.** | | `ProductId` | `guid` | Associated product. | | `JobTypeId` | `guid` | Deliverable type covered by the contract. | | `Value` | `number` | Contract value. | | `StartDateUtc` | `datetime` | Contract start date (UTC). | | `EndDateUtc` | `datetime` | Contract end date (UTC). | | `OwnerId` | `guid` | Contract owner (user). | | `IsDraft` | `boolean` | Whether the contract is created as a draft. | | `WorkflowStateId` | `guid` | Initial workflow stage. | | `IsActivated` | `boolean` | Whether the contract is active. | | `BrandId` | `guid` | Brand, used only as a fallback when the associated Product has none of its own. | `RateCardTypeNumber` isn't listed above on purpose — it's accepted by the payload but has no effect at all; on the server it's a read-only value computed from other contract data, not something that can be set. ```json { "DocumentTypeName": "Estimate", "Actions": { "Document": { "DocumentType": "Estimate", "DocumentActionType": "Post", "Estimate": { "Name": "Q1 campaign estimate", "JobTypeId": "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d", "ProjectId": "3d9c1b3a-1a2b-4c3d-9e0f-1a2b3c4d5e6f", "ClientId": "94177d4d-670b-47b9-a3ff-f05bb4deaf6e", "CompanyId": "92768571-b454-4cdc-8b68-6f7c6aa8e386", "DepartmentId": "5b2e1f6a-3c4d-4e5f-8a9b-1c2d3e4f5a6b", "ProductId": "8f77ad60-228d-4d07-a3f5-ff5ee2e64d8e", "CurrencyId": "12bb8ac2-1729-4be3-a587-0705c4888211", "IsDraft": true, "DocumentBrief": { "DocumentTypeName": "Estimate", "Text": "" } } } } } ``` Fields under `Actions.Document.Estimate`: | Field | Type | Description | |---|---|---| | `Name` | `string` | Estimate name. | | `JobTypeId` | `guid` | Deliverable type the estimate is for. | | `ProjectId` | `guid` | Parent project. | | `ContractId` | `guid` | Associated contract. | | `DeliverableId` | `guid` | Associated Deliverable. | | `ClientId` | `guid` | Client the estimate belongs to. | | `CompanyId` | `guid` | Owning company. | | `DepartmentId` | `guid` | Owning department. | | `ProductId` | `guid` | Associated product. | | `CurrencyId` | `guid` | Currency used for the estimate's financials. | | `PaymentConditionId` | `guid` | Payment condition. | | `WorkflowStateId` | `guid` | Initial workflow stage. | | `IsDraft` | `boolean` | Whether the estimate is created as a draft. | | `IsActivated` | `boolean` | Whether the estimate is active. | | `BusinessObjectTypeId` | `guid` | Business object type. | | `AllowsTimesheet` | `boolean` | Whether timesheets can be logged against it. | | `EstimateCopyId` | `guid` | Optional. Copies the items from another existing estimate into this one after creation. | `CreatedOn` and `Exchange` are accepted but always recomputed by the server on creation (current timestamp, and the currency's own sell rate) — any submitted value is discarded. ```json { "DocumentTypeName": "Expense", "Actions": { "Document": { "DocumentType": "Expense", "DocumentActionType": "Post", "Expense": { "DocumentNumber": "EXP-2025-001", "CompanyId": "92768571-b454-4cdc-8b68-6f7c6aa8e386", "DepartmentId": "5b2e1f6a-3c4d-4e5f-8a9b-1c2d3e4f5a6b", "CurrencyId": "12bb8ac2-1729-4be3-a587-0705c4888211", "PaymentConditionId": "e5f6a7b8-c9d0-4be1-8f2a-4b5c6d7e8f9a", "SupplierId": "f6a7b8c9-d0e1-4cf2-903b-5c6d7e8f9a0b", "TypeId": "a7b8c9d0-e1f2-4d03-914c-6d7e8f9a0b1c", "Emission": "2025-01-15T00:00:00Z", "Due": "2025-02-15T00:00:00Z", "Remarks": "Supplier invoice for January services", "DocumentBrief": { "DocumentTypeName": "Expense", "Text": "" } } } } } ``` Fields under `Actions.Document.Expense`: | Field | Type | Description | |---|---|---| | `DocumentNumber` | `string` | External/reference document number. | | `CompanyId` | `guid` | Owning company. | | `DepartmentId` | `guid` | Owning department. | | `CurrencyId` | `guid` | Currency used for the expense. | | `PaymentConditionId` | `guid` | Payment condition. | | `SupplierId` | `guid` | Supplier the expense is billed from. | | `EmployeeId` | `guid` | Employee associated with the expense. | | `TypeId` | `guid` | Expense type. | | `Emission` | `datetime` | Emission date. | | `Due` | `datetime` | Due date. | | `Exchange` | `number` | Exchange rate applied. | | `Remarks` | `string` | Free-text remarks. | | `ExpenseCopyId` | `guid` | Optional. Copies the items from another existing expense into this one (and attempts to activate each copied item) after creation. | `ExpensePostModel` has no `WorkflowStateId` field — an Expense's initial workflow state is derived automatically from the **creating user's own** company/department defaults, computed before `CompanyId`/`DepartmentId` from the payload are applied. If those differ from the calling user's own defaults, the resulting workflow state may not match what you submitted. ```json { "DocumentTypeName": "ExpenseItem", "Actions": { "Document": { "DocumentType": "ExpenseItem", "DocumentActionType": "Post", "ExpenseItem": { "ExpenseItemTypeId": "b8c9d0e1-f2a3-4e14-9257-7d8e9f0a1b2c", "ExpenseItemGroup": "Travel", "ExpenseSheetId": "6f5e4d3c-2b1a-4c3d-9e0f-1a2b3c4d5e6f", "ClientId": "94177d4d-670b-47b9-a3ff-f05bb4deaf6e", "ProjectId": "3d9c1b3a-1a2b-4c3d-9e0f-1a2b3c4d5e6f", "ValueWithVat": 120.0, "ValueWithoutVat": 100.0, "VatId": "c9d0e1f2-a3b4-4f25-9368-8e9f0a1b2c3d", "Billable": true, "DocumentBrief": { "DocumentTypeName": "ExpenseItem", "Text": "" } } } } } ``` Fields under `Actions.Document.ExpenseItem`: | Field | Type | Description | |---|---|---| | `ExpenseItemTypeId` | `guid` | Expense item type. **Required.** | | `ExpenseItemGroup` | `string` | Expense item group/category. **Required.** | | `ExpenseSheetId` | `guid` | Parent Expense this item belongs to. Required in practice — creation fails without it. | | `ClientId` | `guid` | Client associated with the item. | | `ProjectId` | `guid` | Project associated with the item. | | `DeliverableId` | `guid` | Deliverable associated with the item. | | `EstimateId` | `guid` | Estimate associated with the item. | | `ProductId` | `guid` | Product associated with the item. | | `SupplierId` | `guid` | Supplier for the expense item. | | `JobTypeId` | `guid` | Deliverable type. | | `DepartmentId` | `guid` | Owning department. | | `ValueWithVat` | `number` | Item value including VAT. | | `ValueWithoutVat` | `number` | Item value excluding VAT. | | `VatId` | `guid` | VAT rate applied. | | `Billable` | `boolean` | Whether the item is billable to the client. Defaults to `true` if omitted. | | `Paid` | `boolean` | Whether the item is already marked as paid. | Use `ExpenseSheetId`, not `ExpenseId` — the latter is never read anywhere in the codebase and has no effect regardless of what's submitted. `EmployeeId` is also ignored on creation: the server always attributes the item to the calling user's own employee record. If `Document` (a document-search reference, not shown above) is supplied, it overrides `ClientId`/`ProjectId`/`DeliverableId`/`EstimateId`/`ProductId` based on its own type. ```json { "DocumentTypeName": "RateCard", "Actions": { "Document": { "DocumentType": "RateCard", "DocumentActionType": "Post", "RateCard": { "Name": "Standard 2025 Rate Card", "Number": "RC-2025-001", "CompanyId": "92768571-b454-4cdc-8b68-6f7c6aa8e386", "CurrencyId": "12bb8ac2-1729-4be3-a587-0705c4888211", "JobTypeId": "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d", "Active": true, "BeginDate": "2025-01-01T00:00:00Z", "EndDate": "2025-12-31T00:00:00Z" } } } } ``` Fields under `Actions.Document.RateCard`: | Field | Type | Description | |---|---|---| | `Name` | `string` | Rate card name. **Required.** | | `Number` | `string` | Rate card number. **Required.** | | `CompanyId` | `guid` | Owning company. **Required.** | | `CurrencyId` | `guid` | Currency used. **Required.** | | `JobTypeId` | `guid` | Deliverable type. **Required.** | | `Active` | `boolean` | Whether the rate card is active. | | `BeginDate` | `datetime` | Start date. **Required**, must be earlier than `EndDate`. | | `EndDate` | `datetime` | End date. **Required.** | `RateCard` doesn't support `DocumentBrief` — there's no such field on this document type. ```json { "DocumentTypeName": "PriceTable", "Actions": { "Document": { "DocumentType": "PriceTable", "DocumentActionType": "Post", "PriceTable": { "Name": "Standard 2025 Price Table", "Number": "PT-2025-001", "CompanyId": "92768571-b454-4cdc-8b68-6f7c6aa8e386", "CurrencyId": "12bb8ac2-1729-4be3-a587-0705c4888211", "JobTypeId": "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d", "Active": true, "BeginDate": "2025-01-01T00:00:00Z", "EndDate": "2025-12-31T00:00:00Z" } } } } ``` Fields under `Actions.Document.PriceTable` — identical shape to `RateCard`: | Field | Type | Description | |---|---|---| | `Name` | `string` | Price table name. **Required.** | | `Number` | `string` | Price table number. **Required.** | | `CompanyId` | `guid` | Owning company. **Required.** | | `CurrencyId` | `guid` | Currency used. **Required.** | | `JobTypeId` | `guid` | Deliverable type. **Required.** | | `Active` | `boolean` | Whether the price table is active. | | `BeginDate` | `datetime` | Start date. **Required**, must be earlier than `EndDate`. | | `EndDate` | `datetime` | End date. **Required.** | `PriceTable` doesn't support `DocumentBrief` — there's no such field on this document type. ```json { "DocumentTypeName": "Request", "Actions": { "Document": { "DocumentType": "Request", "DocumentActionType": "Post", "Request": { "Name": "New product request", "ClientId": "94177d4d-670b-47b9-a3ff-f05bb4deaf6e", "CompanyId": "92768571-b454-4cdc-8b68-6f7c6aa8e386", "JobTypeId": "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d", "ProductId": "8f77ad60-228d-4d07-a3f5-ff5ee2e64d8e", "BeginDateUtc": "2025-01-01T00:00:00Z", "EndDateUtc": "2025-03-01T00:00:00Z", "IsDraft": true, "DocumentBrief": { "DocumentTypeName": "Request", "Text": "" } } } } } ``` Fields under `Actions.Document.Request`: | Field | Type | Description | |---|---|---| | `Name` | `string` | Request name. | | `ClientId` | `guid` | Client the request belongs to. | | `CompanyId` | `guid` | Owning company. | | `ContractId` | `guid` | Associated contract. | | `JobTypeId` | `guid` | Deliverable type being requested. | | `ProductId` | `guid` | Associated product. | | `BrandId` | `guid` | Brand, used only as a fallback when the associated Product has none of its own. | | `OwnerId` | `guid` | Request owner (user). | | `BeginDateUtc` | `datetime` | Start date (UTC). | | `EndDateUtc` | `datetime` | End date (UTC). | | `IsDraft` | `boolean` | Whether the request is created as a draft. | | `IsActivated` | `boolean` | Whether the request is active. | | `WorkflowStateId` | `guid` | Initial workflow stage. | | `BusinessObjectTypeId` | `guid` | Business object type. | | `Priority` | `int` | Priority code. | | `Markets` | `guid[]` | Associated market IDs. | ```json { "DocumentTypeName": "Tender", "Actions": { "Document": { "DocumentType": "Tender", "DocumentActionType": "Post", "Tender": { "Name": "Media buying tender 2025", "DepartmentId": "5b2e1f6a-3c4d-4e5f-8a9b-1c2d3e4f5a6b", "CommercialClientId": "94177d4d-670b-47b9-a3ff-f05bb4deaf6e", "JobTypeId": "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d", "CommercialProductId": "8f77ad60-228d-4d07-a3f5-ff5ee2e64d8e", "EndDate": "2025-06-30T00:00:00Z", "TotalPrice": 25000.0 } } } } ``` Fields under `Actions.Document.Tender`: | Field | Type | Description | |---|---|---| | `Name` | `string` | Tender name. **Required.** | | `Description` | `string` | Free-text description. | | `DepartmentId` | `guid` | Owning department. **Required** — Company and Division are derived from it, not submitted directly. | | `CommercialClientId` | `guid` | Client the tender is for. **Required.** | | `JobTypeId` | `guid` | Deliverable type. **Required.** | | `CommercialProductId` | `guid` | Associated product. | | `ProjectId` | `guid` | Associated project. | | `BrandId` | `guid` | Brand. | | `ContractId` | `guid` | Associated contract. | | `CurrencyId` | `guid` | Currency. Falls back to the department's company currency if omitted. | | `BusinessObjectTypeId` | `guid` | Business object type. Falls back to the Deliverable type's own business object type if omitted. | | `EndDate` | `datetime` | Tender end date. If omitted, the server substitutes a default a few months out rather than rejecting the request. | | `TotalPrice` | `number` | Total tender value. | `Tender` doesn't support `DocumentBrief` — there's no such field on this document type. Unlike the other document types above, creating a Tender through this endpoint also doesn't generate a history/audit entry. #### Document Brief Where supported (see the [Supported Document Types](#supported-document-types) table above), `DocumentBrief` is nested inside the type-specific object and has the same shape for every type: | Field | Type | Description | |---|---|---| | `DocumentTypeName` | `string` | Document type the brief belongs to — same value as the outer `DocumentTypeName`. | | `Text` | `string` | Content of the brief. | #### Response `201 Created` — the created **Post** (feed entry), not the document itself. Its `DocumentId` field holds the ID of the newly created document. Most `Id` fields across the tabs above reference records that already exist in your tenant (clients, companies, products, etc.). The [Data Extraction](../api/data-extraction-api.md) queries under `docs/api/data-extraction` are available to look up the correct GUID for each of these before building a payload — don't hardcode IDs from another tenant or environment. #### Testing with Postman The same requests can be sent from the [Postman collection](#postman-collection): | Field | Value | |---|---| | Method | `POST` | | URL | `https://apiv2-{{Tenant}}.skillsworkflow.com/api/posts` | | Body | `raw` / `JSON` — paste any of the payloads above | --- ## Configuration URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/application/application-configuration Summary: This method can be used to get the current environment configuration. ## get #### Description This method can be used to get the current environment configuration. #### Method(s) ```javascript 1 declare function get(): IServerConfiguration; ``` #### Basic Usage ```javascript SW.Application.Configuration.get(); ``` --- ## Current User URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/document/document-currentUser Summary: A sub namespace of Document, exclusive for the current logged user operations --- A sub namespace of Document, exclusive for the current logged user operations --- ## getClients #### Description This method can be used to get current logged user clients. #### Method(s) ```js {3} 1 declare function getClients( 2 params: { 3 name?: string, 4 skip?: number, 5 take?: number 6 } = { 7 name: "", 8 skip: 0, 9 take: 0 10 } 11 ): Promise; ``` Parameter Type Required Defaults Description name string false Name to filter the search skip number false 0 Allows you skip the first results returned by the method take number false 0 Set a maximum number of result you want to return #### Basic Usage ```javascript SW.Document.CurrentUser.getClients({ name:"SkillsWorkflow", skip: 0, take: 20}); ``` --- ## getCompanies #### Description This method can be used to get current logged user companies. #### Method(s) ```js {3} declare function getCompanies(params: { name?: string, skip?: number, take?: number } = { name: "", skip: 0, take: 0 }); ``` Parameter Type Required Defaults Description name string false Name to filter the search skip number false 0 Allows you skip the first results returned by the method take number false 0 Set a maximum number of result you want to return #### Basic Usage ```javascript SW.Document.CurrentUser.getCompanies({ name:"SkillsWorkflow", skip: 0, take: 20}); ``` --- ## getDivisons #### Description This method can be used to get current logged user divisions. #### Method(s) ```js {3} declare function getDivisions( params: { name?: string, skip?: number, take?: number } = { name: "", skip: 0, take: 0 } ): ``` Parameter Type Required Defaults Description name string false Name to filter the search skip number false 0 Allows you skip the first results returned by the method take number false 0 Set a maximum number of result you want to return #### Basic Usage ```javascript SW.Document.CurrentUser.getDivisions({ name:"SkillsWorkflow", skip: 0, take: 20}); ``` --- ## getInfo #### Description This method can be used to get current logged user information. #### Method(s) ```js {3} 1 declare function getInfo(): UserInfo ``` #### Basic Usage ```javascript SW.Document.CurrentUser.getInfo(); ``` --- ## hasAllRoles #### Description This method can be used to check if the current logged user has all given roles. #### Method(s) ```js {3} 1 declare function hasAllRoles(roles: string[]): boolean; ``` Parameter Type Required Defaults Description roles string[] true Roles to check #### Basic Usage ```javascript SW.Document.CurrentUser.hasAllRoles(["Admin", "Manager"]); ``` #### Response ```javascript false ``` --- ## hasAnyRoles #### Description This method can be used to check if the current logged user has any of the given roles. #### Method(s) ```js {3} 1 declare function hasAnyRoles(roles: string[]): boolean; ``` Parameter Type Required Defaults Description roles string[] true Roles to check #### Basic Usage ```javascript SW.Document.CurrentUser.hasAnyRoles(["Admin", "Manager"]); ``` #### Response ```javascript true ``` --- ## hasRole #### Description This method can be used to check if the current logged user has the given role. #### Method(s) ```js {3} 1 declare function hasRole(roleName: string): boolean; ``` Parameter Type Required Defaults Description roleName string true Role to check #### Basic Usage ```javascript SW.Document.CurrentUser.hasRole("Admin"); ``` #### Response ```javascript false ``` --- ## hasRoles #### Description This method can be used to check if the current logged user has each of the given roles or not. #### Method(s) ```js {3} 1 declare function hasRoles(roles: string[]): { [roleName: string]: boolean }; ``` Parameter Type Required Defaults Description roles string[] true Roles to check #### Basic Usage ```javascript SW.Document.CurrentUser.hasRoles(["Admin", "Manager"]); ``` #### Response ```javascript { Admin: false, Manager: true } ``` --- ## Custom Table URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/document/customTable Summary: A sub namespace of Document, exclusive for custom table operations. A sub namespace of Document, exclusive for custom table operations. **Namespace:** `SW.Document.CustomTable` --- --- ## Custom Tables API URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/custom-tables-api Summary: The Custom Tables API allows you to programmatically create, read, update, and delete data in user-defined custom tables. ### Description The Custom Tables API allows you to programmatically create, read, update, and delete data in user-defined custom tables. Custom tables extend the Skills Workflow data model with additional, tenant-specific tables for storing structured data. If you are working inside Skills Workflow workspaces or automations, prefer using the **SDK methods** (`SW.Document.CustomTable.*`) documented in the [SDK Reference](/docs/build-and-extend/sdk/document/customTable) instead of calling the API directly. --- --- ## Data URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/data Summary: The namespace Data provides to developers, methods to easily manipulate data. # Data The namespace Data provides to developers, methods to easily manipulate data. ```javascript //accessing to data methods SW.Data.{methodName} ``` --- ## aggregate #### Description This method can be used to aggregate data and perform operations, like sum, count, max or custom, when aggregating data. It can also remove rows where a field is equal to zero (noZeros) and order them (sort). #### Method(s) ```javascript 1 function aggregate( dataArray: Object[], aggregateBy: [{ Name: string; Field: string }], params?: { operations: [ { Name: string; Field: string; OperationType: "sum" | "count" | "max" | "percent" | "custom"; CustomFunction?: Function; } ]; sort: { fields: string[]; order: "ascendent" | "descendent"; }; noZeros: string[]; } ): any[] ``` Parameter Type Required Defaults Description dataArray Object[] true Data array to aggregate aggregateBy Name string true Name of the aggregated field in the new set of data aggregateBy Field string true Field to use in the aggregation operations Name string false Operation result field name operations Field string false Field to use in the operation OperationType "sum" | "count" | "max" | "percent" | "custom" false Operation to perform CustomFunction Function false Operation to perform when operationType is custom sort fields string[] false Fields to use in the order by sort order "ascendent" | "descendent" false Order type noZeros string[] false To remove rows where a given field is zero #### Basic Usage ```javascript SW.Data.aggregate(dataArray, [{ Name: 'AggregatedName', Field: 'UserName' }], { operations: [ { Name: 'SumAge', Field: 'Age', OperationType: 'sum' }, { Name: 'MaxAge', Field: 'Age', OperationType: 'max' }, { Name: 'CountRows', OperationType: 'count' }, { Name: 'AverageYearsInJob', Field: 'Age', Reference: 'NumberOfJobs' OperationType: 'percent' } ], grandTotals: [ { Name: "AverageYearsInJobTotal", Field: "Age", Reference: "NumberOfJobs", OperationType: "percent" } ], sort: { fields: ['AggregatedName', 'MaxAge']; order: "ascendent"; }, noZeros: ['SumAge'] }); ``` #### Response It will return a new set of data aggregated by UserName with the fields: - AggregatedName: choosen name for the aggregation field - SumAge: sum of the age where the UserName is the same - MaxAge: max age where the UserName is the same - CountRows: count of the rows where the UserName is the same - AverageYearsInJob: will apply the following calculation Field / Reference, in this case Age / NumberOfJobs - GrandTotals: - AverageYearsInJobTotal: it will sum all of the Age and NumberOfJobs and divide them It will be sorted by the fields AggregatedName and MaxAge in an ascendent order and it will remove rows where the SumAge is equal to zero. #### Example --- ## Data Extraction API URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction-api Summary: The Data Extraction API enables you to export data from Skills Workflow into external tools and systems—such as Excel, Power BI, or custom applications—by… ## Overview The Data Extraction API enables you to export data from Skills Workflow into external tools and systems—such as Excel, Power BI, or custom applications—by dynamically querying named data sets. ### Purpose The Data Extraction API is intended for reading and exporting data from Skills Workflow in a structured and efficient way. It is ideal for reporting, dashboards, and integration with external BI or analytics tools. ### Use Cases Export data from Skills Workflow to: - Excel, Power BI, Google Sheets - Custom dashboards or internal reporting systems - Third-party analytics tools - Automation tools like Zapier or Make (Integromat) - Data warehouses or ETL pipelines ### Key Limitations - Read-only: This API does not support creating or updating records. - Depends on predefined data sets. - Pagination recommended: Use pagination (skip/take) for large queries to avoid timeouts or incomplete results. - Rate limits may apply: For high-frequency requests, consider caching or batching. --- ## Getting Started ### Authentication Before calling any endpoint, you must obtain the following credentials from our Support team: - **App Key** (`X-AppId`) - **App Secret** (`X-AppSecret`) - **Tenant ID** (`X-AppTenant`) > These are provided by the support team upon request. Include them in each request via HTTP headers: ```http X-AppTenant: X-AppId: X-AppSecret: X-AppUser: # Optional, if user-scoped filtering is required Content-Type: application/json ``` ### Environments The API is available in four environments, depending on your subscription plan: - **Development** - **Test** - **UAT** - **Production** Each environment has its own base URL: ``` {{ApiUrl}}/api/v3/analytics ``` ### Postman Collection To facilitate testing of the available queries, we provide a Postman collection file with all endpoints configured. You can download it from the link below: [Download Postman Collection - Data Extraction](/templates/data-extraction-postman-collention.json) After downloading, make sure to configure the variables `{{ApiUrl}}`, `{{TenantId}}`, `{{AppId}}`, `{{AppSecret}}`, and `{{UserId}}` according to the credentials you have been given. ### Rate Limits Each request must complete within **30 seconds**. - **Apply filters** to narrow the data set. - **Use pagination** (`skip` / `take`) to retrieve large data sets in chunks. ### Filtering Data To flexibly extract data, use the **`queryBuilder`** object in your POST body. It supports: | Property | Type | Description | |------------|----------|---------------------------------------------------------------------------------------------------| | `skip` | integer | Number of records to skip (for pagination). | | `take` | integer | Maximum number of records to return. | | `orderBy` | array | List of `{ field, direction }` objects to sort results. | | `fields` | array | List of field names to include in the response. | | `filters` | array | Complex filters combining expressions, e.g. `[["Status","=","Open"],"and",["Priority",">",2]]`. | ### Filter Operations The following table lists available filter operations by data type. The Query Builder uses the first operation in each array as the default operation for the specified data type. | Data Type | Filter Operations | |----------------|---------------------------------------------------------------------------------------------------| | `string` | `contains`, `notcontains`, `startswith`, `endswith`, `=`, `<>`, `isblank`, `isnotblank` | | `numeric` | `=`, `<>`, `<`, `>`, `<=`, `>=`, `between`, `isblank`, `isnotblank` | | `date`, `datetime` | `=`, `<>`, `<`, `>`, `<=`, `>=`, `between`, `isblank`, `isnotblank` | | `boolean` | `=`, `<>`, `isblank`, `isnotblank` | | `object` | `isblank`, `isnotblank` | ```json { "queryBuilder": { "skip": 0, "take": 100, "orderBy": [ { "field": "UserId", "direction": "asc" } ], "fields": ["Team", "UserId"], "filters": [ ["Team", "=", "Executor"], "or", ["Team", "=", "Requester"] ] } } ``` --- ### Discovering Available Fields To know which fields you can request, perform an initial call with only pagination: ```bash POST {{ApiUrl}}/api/v3/analytics/named-query/DE-Clients/dynamic-execute Headers: X-AppTenant: X-AppId: X-AppSecret: Body: { "queryBuilder": { "skip": 0, "take": 100 } } ``` This returns up to 100 records and reveals all available properties in the response schema, which you can then reference in subsequent `queryBuilder.fields` and `queryBuilder.filters`. --- ## Endpoints The collection includes several `dynamic-execute` endpoints, each under: ``` POST /api/v3/analytics/named-query/{NamedQuery}/dynamic-execute ``` Where `{NamedQuery}` is one of: ### Named Queries and Available Filters Below is a list of available Named Queries and their applicable filters (if any). | NamedQuery | Description | Filters | Columns | Details | |-----------|-------------|---------|---------|---------| | DE-Bills | Extracts data for bills. | — | 54 | [View](data-extraction/de-bills.md) | | DE-Leaves | #Description Contains documents with information about vaca… | — | 17 | [View](data-extraction/de-leaves.md) | | DE-Assignments | Extracts the teams of users associated with each document. | — | 10 | [View](data-extraction/de-assignments.md) | | DE-Attendances | Extracts data on attendances. | — | 16 | [View](data-extraction/de-attendances.md) | | DE-Brands | Extracts the list of brands. | — | 5 | [View](data-extraction/de-brands.md) | | DE-BusinessObjectTypes | Extracts business object types. | — | 6 | [View](data-extraction/de-businessobjecttypes.md) | | DE-Cities | Extracts all cities. | — | 4 | [View](data-extraction/de-cities.md) | | DE-Clients | Extracts the list of clients. | — | 30 | [View](data-extraction/de-clients.md) | | DE-ClientsCompanies | Extracts the information about what companies have access t… | — | 4 | [View](data-extraction/de-clientscompanies.md) | | DE-Comments | Extracts comments from the feed. | — | 13 | [View](data-extraction/de-comments.md) | | DE-CommentsReplies | Extracts replies of comments. | — | 12 | [View](data-extraction/de-commentsreplies.md) | | DE-Companies | Extracts the list of companies. | — | 25 | [View](data-extraction/de-companies.md) | | DE-CompaniesAdditionalInformation | Extracts the custom fields associated with the companies. | — | 3 | [View](data-extraction/de-companiesadditionalinformation.md) | | DE-Contracts | Extracts contracts information. | — | 0 | [View](data-extraction/de-contracts.md) | | DE-Countries | Extracts the list of countries. | — | 2 | [View](data-extraction/de-countries.md) | | DE-Currencies | Extracts the list of currencies. | — | 5 | [View](data-extraction/de-currencies.md) | | DE-Departments | Extracts the list of departments. | — | 7 | [View](data-extraction/de-departments.md) | | DE-Descriptions | Extracts the different versions of the descriptions of docu… | — | 12 | [View](data-extraction/de-descriptions.md) | | DE-Divisions | Extracts the list of divisions. | — | 4 | [View](data-extraction/de-divisions.md) | | DE-Employees | Extracts employees. | — | 9 | [View](data-extraction/de-employees.md) | | EstimatedPlannedActualMonthly | System generic extraction of estimated, planned and actual,… | — | 45 | [View](data-extraction/estimatedplannedactualmonthly.md) | | DE-Estimates | Extracts the list of estimates. | — | 0 | [View](data-extraction/de-estimates.md) | | DE-EstimatesBillingConditions | — | — | 21 | [View](data-extraction/de-estimatesbillingconditions.md) | | DE-EstimatesCount | Gets the count of estimates for the given filters. | — | 1 | [View](data-extraction/de-estimatescount.md) | | DE-EstimatesQuotes | Extracts the estimate details. | — | 62 | [View](data-extraction/de-estimatesquotes.md) | | DE-EstimatesQuotesCount | Counts the occurrences of quotes. | — | 1 | [View](data-extraction/de-estimatesquotescount.md) | | DE-EstimatesQuotesMonthCount | Gets the count of estimate quotes for the given filters. | — | 0 | [View](data-extraction/de-estimatesquotesmonthcount.md) | | DE-ExpenseSheets | Extracts expense sheets for integration purposes. | — | 22 | [View](data-extraction/de-expensesheets.md) | | DE-ExpenseType | Extracts expense items types. | — | 15 | [View](data-extraction/de-expensetype.md) | | DE-Expenses | Extracts expenses for integration purposes. | — | 20 | [View](data-extraction/de-expenses.md) | | DE-History | Extract history of documents. | — | 17 | [View](data-extraction/de-history.md) | | DE-Holidays | Extracts the list of holidays. | — | 6 | [View](data-extraction/de-holidays.md) | | DE-Jobs | Extracts the list of jobs. | — | 44 | [View](data-extraction/de-jobs.md) | | DE-JobsCount | Gets the count of jobs for the given filters. | — | 1 | [View](data-extraction/de-jobscount.md) | | DE-LeavesCount | — | — | 1 | [View](data-extraction/de-leavescount.md) | | DE-LeavesDeleted | Extracts deleted leaves using the parameter ModifiedFrom to… | — | 2 | [View](data-extraction/de-leavesdeleted.md) | | DE-LeavesDeletedCount | Gets the count of deleted leaves for the filters provided. | — | 1 | [View](data-extraction/de-leavesdeletedcount.md) | | DE-Products | Extracts the list of products. | — | 7 | [View](data-extraction/de-products.md) | | DE-Projects | Extracts a list of projects. | — | 53 | [View](data-extraction/de-projects.md) | | DE-ProjectsClassifications | Extract project classifications. | — | 9 | [View](data-extraction/de-projectsclassifications.md) | | DE-ProjectsCount | Gets the count of projects for the provided filters. | — | 0 | [View](data-extraction/de-projectscount.md) | | DE-ProjectsAdditionalInformation | Extracts additional information from projects. | — | 4 | [View](data-extraction/de-projectsadditionalinformation.md) | | DE-ProjectsPlannedTime | Extract projects. | — | 27 | [View](data-extraction/de-projectsplannedtime.md) | | DE-ProjectsPlannedTimeCount | Gets the count of projects planned time for the provided fi… | — | 0 | [View](data-extraction/de-projectsplannedtimecount.md) | | DE-ProjectsTypes | Extract projects types. | — | 11 | [View](data-extraction/de-projectstypes.md) | | DE-PurchaseOrders | Extracts purchase orders data from the system. | — | 49 | [View](data-extraction/de-purchaseorders.md) | | DE-RateCardsColumns | Extraction of rate cards' columns. | — | 20 | [View](data-extraction/de-ratecardscolumns.md) | | DE-Requests | Extracts requests data. | — | 51 | [View](data-extraction/de-requests.md) | | DE-Services | Extracts the existing services. | — | 16 | [View](data-extraction/de-services.md) | | DE-ServicesGroups | Extracts the services groups. | — | 6 | [View](data-extraction/de-servicesgroups.md) | | DE-Stages | Extracts the list of stages of the workflows. | — | 4 | [View](data-extraction/de-stages.md) | | DE-Suppliers | Extracts suppliers for integration purposes. | — | 37 | [View](data-extraction/de-suppliers.md) | | DE-Taxes | Extracts information about taxes. | — | 9 | [View](data-extraction/de-taxes.md) | | DE-TimeSheets | Extracts the time entered in time sheets. | — | 38 | [View](data-extraction/de-timesheets.md) | | DE-TimeSheetsCount | Gets the count of time sheets for the filters provided. | — | 0 | [View](data-extraction/de-timesheetscount.md) | | DE-TimeSheetsDeleted | Extracts time sheets that have been deleted. | — | 2 | [View](data-extraction/de-timesheetsdeleted.md) | | DE-TimeSheetsDeletedCount | Gets the count of deleted time sheet for the provided filte… | — | 1 | [View](data-extraction/de-timesheetsdeletedcount.md) | | DE-Transitions | Extracts the list of existing transitions. | — | 27 | [View](data-extraction/de-transitions.md) | | DE-Types | Extracts job types. | — | 39 | [View](data-extraction/de-types.md) | | DE-Typologies | Extracts the list of typologies of users. | — | 15 | [View](data-extraction/de-typologies.md) | | DE-TypologyGroups | Extracts user typology groups of user typologies. | — | 4 | [View](data-extraction/de-typologygroups.md) | | DE-TypologyGroupsCompanies | Extracts typology grous associated to companies | — | 5 | [View](data-extraction/de-typologygroupscompanies.md) | | DE-TypologyGroupsDepartments | Extracts typology groups associated to departments. | — | 5 | [View](data-extraction/de-typologygroupsdepartments.md) | | DE-UserCosts | Extracts cost of users. | — | 12 | [View](data-extraction/de-usercosts.md) | | DE-UserTypes | Extracts the user types. | — | 2 | [View](data-extraction/de-usertypes.md) | | DE-Users | Extracts the list of users. | — | 30 | [View](data-extraction/de-users.md) | | DE-UsersAdditionalInformation | — | — | 3 | [View](data-extraction/de-usersadditionalinformation.md) | | DE-WorkTypes | Extracts the work types list. | — | 4 | [View](data-extraction/de-worktypes.md) | | DE-Workloads | Extracts data from Workloads. | — | 13 | [View](data-extraction/de-workloads.md) | | DE-EstimatesQuotesMonth | Extracts all data from estimates. | — | 32 | [View](data-extraction/de-estimatesquotesmonth.md) | --- ## Example Usage ### Retrieve Filtered Assignments ```bash POST {{ApiUrl}}/api/v3/analytics/named-query/DE-Assignments/dynamic-execute Headers: X-AppTenant: X-AppId: X-AppSecret: X-AppUser: Body: { "queryBuilder": { "skip": 0, "take": 50, "orderBy": [ { "field": "User", "direction": "asc" } ], "fields": ["Team", "UserId", "AssignmentDate"], "filters": [ ["Team", "=", "Executor"], "or", ["Team", "=", "Requester"] ] } } ``` #### Sample Response ```json { "data": [ { "Team": "Executor", "UserId": "U123", "AssignmentDate": "2025-04-01T09:30:00Z" }, { "Team": "Requester", "UserId": "U456", "AssignmentDate": "2025-04-02T14:45:00Z" } // … ], "totalCount": 124 } ``` ## Scheduled Data Extraction You can configure **Schedules** in Skills Workflow to automate recurring data exports. This method is ideal for generating files (e.g., CSV) that can be directly consumed by external tools such as Power BI, Excel, Tableau, and others. ### Overview Schedules allow you to: - Define a **Query** to extract data (same data source as the API). - Choose an export **Format** (e.g., `.csv`). - Set a **Cron Expression** to determine when the export should occur. Once scheduled, the system will run the query at the specified time and generate a downloadable file. ### Configuration Example Here’s a configuration example of a schedule set up to export timesheet data every day at 5:00 AM UTC: _The above screenshot shows the “DE-TimeSheets” query being scheduled to export daily._ ### Cron Expression The **Cron Expression (UTC)** field defines when the job should run. For example: ``` 5 0 * * * ``` This runs the job daily at 5:00 AM UTC. We recommend running schedules outside working hours to minimize system load and ensure the data is complete. --- ## Data Relationships The diagram below shows the hierarchy between Data Extractions. Use the dropdown to focus on a specific DE and its immediate parent/children, or select "All" to view the full tree. Click any node to inspect its output columns. --- ## Datetime URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/utils/utils-datetime Summary: A sub namespace of Utils, exclusive for date operations --- # Datetime A sub namespace of Utils, exclusive for date operations --- ## convertMinutesToDate #### Description This method can be used to convert minutes into a date. #### Method(s) ```javascript function convertMinToDate(totalMinutes: number): Date ``` Parameter Type Required Defaults Description totalMinutes number true Minutes to convert to date #### Basic Usage ```javascript SW.Utils.Datetime.convertMinutesToDate(63984503); ``` #### Response ```javascript "Thu Aug 26 2021 16:23:00 GMT+0100 (Western European Summer Time)"; ``` --- ## convertToUtc #### Description This method can be used to convert a local date to utc date. #### Method(s) ```javascript function convertToUtc(date: Date): Date ``` Parameter Type Required Defaults Description date Date true Date to convert to utc #### Basic Usage ```javascript SW.Utils.Datetime.convertToUtc( "Thu Aug 26 2021 16:23:00 GMT+0100 (Western European Summer Time)" ); ``` #### Response ```javascript "Thu Aug 26 2021 15:23:00 GMT+0100 (Western European Summer Time)"; ``` --- ## convertUtcToLocal #### Description This method can be used to convert utc date to a local date. #### Method(s) ```javascript function convertUtcToLocal(utcDate: Date): Date ``` Parameter Type Required Defaults Description utcDate Date true Date to convert to local #### Basic Usage ```javascript SW.Utils.Datetime.convertUtcToLocal("2021-08-25T15:23:26.222Z"); ``` #### Response ```javascript "Wed Aug 25 2021 16:23:26 GMT+0100 (Western European Summer Time)"; ``` #### Example ```javascript {13} { colCount: 2, dataField: "CreatedOnUtc", editorType: "dxDateBox", label: { text: "Created On" }, editorOptions: { type: "datetime", displayFormat: "dd/MMM/yyyy HH:mm", onInitialized: function onInit(e) { var context = workspaceContext; var date = SW.Utils.Datetime.convertUtcToLocal(context.currentDocument.Dto.Request.CreatedOnUtc); e.component.option('value', date); } } } ``` --- ## formatDateToString #### Description This method can be used to convert date to string format "yyyy-MM-dd" or "yyyy-MMMM-dd, hh:mm". #### Method(s) ```javascript function formatDateToString(date: Date, params: { includeTime?: boolean } = { includeTime: false }): string ``` Parameter Type Required Defaults Description utcDate Date true Date to convert to local includeTime boolean false false If to convert with or without time #### Basic Usage ```javascript var date = "Wed Aug 25 2021 16:23:26 GMT+0100 (Western European Summer Time)"; SW.Utils.Datetime.formatDateToString(date); SW.Utils.Datetime.formatDateToString(date, { includeTime: true }); ``` #### Response ```javascript "2021-08-25"; "25 August 2021, 16:23"; ``` --- ## getDateTimeFormat #### Description This method can be used to get the default datetime format. #### Method(s) ```javascript function getDateTimeFormat(): string ``` #### Basic Usage ```javascript SW.Utils.Datetime.getDateTimeFormat(); ``` #### Response ```javascript "dd/MMM/yyyy HH:mm"; ``` --- ## getMinutesInHHMMformat #### Description This method can be used to convert minutes to format HH:mm. #### Method(s) ```javascript function getMinutesInHHMMformat(minutes: number): string ``` Parameter Type Required Defaults Description minutes number true Minutes to convert to HH:mm #### Basic Usage ```javascript SW.Utils.Datetime.getMinutesInHHMMformat(1234); ``` #### Response ```javascript "20:34"; ``` --- ## getTimeRange #### Description This method can be used to get a end date by giving a start date and a range. #### Method(s) ```javascript 1 function getTimeRange(value: Date, shift: DateShift, params: { centerAroundValue?: boolean } = { centerAroundValue: false } ): { startDate: Date, endDate: Date } ``` Parameter Type Required Defaults Description value Date true Start date in range shift DateShift true Range centerAroundValue boolean false If returns exact minutes and seconds #### Basic Usage ```javascript var date = "Wed Aug 25 2021 16:23:26 GMT+0100 (Western European Summer Time)"; SW.Utils.Datetime.getTimeRange(date, { unit: "HOUR", value: 1, id: "HOUR" }); SW.Utils.Datetime.getTimeRange( date, { unit: "HOUR", value: 1, id: "HOUR" }, { centerAroundValue: true } ); ``` #### Response ```javascript { startDate: "Wed Aug 25 2021 16:00:00 GMT+0100 (Western European Summer Time)", endDate: "Wed Aug 25 2021 17:00:00 GMT+0100 (Western European Summer Time)" } { startDate: "Wed Aug 25 2021 16:23:26 GMT+0100 (Western European Summer Time)", endDate: "Wed Aug 25 2021 17:23:26 GMT+0100 (Western European Summer Time)" } ``` --- ## timeAgo #### Description This method can be used to get how much time has passed since a given date. #### Method(s) ```javascript 1 function timeAgo(dateString: string, params: { unitOfTime?: "seconds" | "minutes" | "hours" | "days" | "months" | "years" } = {} ): string | number ``` Parameter Type Required Defaults Description dateString string true Date in string unitOfTime "seconds" | "minutes" | "hours" | "days" | "months" | "years" false Unit of the result #### Basic Usage ```javascript var date = "Wed Aug 25 2021 16:23:26 GMT+0100 (Western European Summer Time)"; SW.Utils.Datetime.timeAgo(date); SW.Utils.Datetime.timeAgo(date, { unitOfTime: "minutes" }); ``` #### Response ```javascript "a minute ago"; 1; ``` --- ## DE-Assignments URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-assignments Summary: Extracts the teams of users associated with each document. Extracts the teams of users associated with each document. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Assignments/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | DocumentId | ass | DocumentOid | | DocumentType | — | right(...) | | DocumentSubType | ass | BusinessObjectTypeName | | TeamId | ast | Oid | | Team | ast | Name | | UserId | usr | Id | | User | usr | Name | | ModifiedOnUtc | ass | ModifiedOnUtc | | ModifiedById | mod | Id | | ModifiedBy | mod | Name | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Assignment | ass | FROM | | AssignmentType | ast | JOIN | | UserLookup | usr | JOIN | | UserLookup | mod | JOIN | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Attendances URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-attendances Summary: Extracts data on attendances. Extracts data on attendances. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Attendances/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Day | — | Day | | UserId | usl | Id | | User | usl | Name | | Hours | — | Hours | | Minutes | — | Minutes | | OffSetTotalMinutes | — | OffSetTotalMinutes | | TardinessTotalMinutes | — | TardinessTotalMinutes | | BreakTotalMinutes | — | BreakTotalMinutes | | HomeOffice | — | HomeOffice | | HalfDay | — | HalfDay | | Time | — | Time | | Type | — | Type | | AdjustedTime | — | AdjustedTime | | Motive | — | Motive | | Offset | — | Offset | | OffsetMinutes | — | OffsetMinutes | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Attendance | atc | FROM | | AttendanceDetail | atd | JOIN | | UserLookup | usl | JOIN | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Bills URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-bills Summary: Extracts data for bills. Extracts data for bills. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Bills/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Oid | doc | Oid | | DocumentOid | doc | Oid | | BillId | doc | Oid | | Bill | doc | Name | | BillNumber | doc | Number | | Due | doc | Due | | Date | doc | Date | | ManagementDate | doc | ManagementDate | | Company | com | Name | | CompanyId | com | Id | | CompanyHasImage | com | HasImage | | ClientGroup | clg | Name | | Client | cli | Name | | ClientId | cli | Id | | ClientHasImage | cli | HasImage | | BillingClient | bcl | Name | | CreatedOnUtc | doc | CreatedOnUtc | | CreatedBy | cre | Name | | CreatedById | cre | Id | | CreatedByHasImage | cre | HasImage | | ModifiedOnUtc | doc | ModifiedOnUtc | | ModifiedBy | mod | Name | | ModifiedById | mod | Id | | ModifiedByHasImage | mod | HasImage | | ProjectId | prj | Oid | | Project | prj | NameAndExternalId | | ContractId | cnt | Oid | | Contract | cnt | NameAndExternalId | | EstimateId | est | Oid | | Estimate | est | NumberAndName | | Department | dep | Name | | Currency | cur | Name | | CurrencyIsoCode | cur | IsoCode | | CurrencySymbol | cur | Symbol | | PaymentCondition | pcn | Name | | YourReference | doc | YourReference | | ValueWithoutVat | doc | ValueWithoutVat | | VatValue | doc | VatValue | | ValueWithVat | doc | ValueWithVat | | External | doc | External | | ExternalId | doc | ExternalId | | ExternalError | doc | ExternalError | | Paid | doc | Paid | | PaidValue | doc | PaidValue | | Remarks | doc | Remarks | | Stage | wfs | Name | | StageColor | wfs | Color | | StateType | wst | Name | | StageType | wst | Name | | AlreadyRead | — | iif(...) | | CurrentUserInTeam | — | iif(...) | | BaseObjectReadId | bor | Oid | | FavoriteId | uf | Oid | | IsFavorite | — | iif(...) | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Bill | doc | FROM | | Client | bcl | JOIN | | ClientLookup | cli | JOIN | | ClientGroup | clg | LEFT JOIN | | WorkflowState | wfs | JOIN | | WorkflowStateType | wst | JOIN | | UserLookup | cre | JOIN | | UserLookup | mod | JOIN | | CompanyLookup | com | JOIN | | Currency | cur | JOIN | | PaymentCondition | pcn | JOIN | | DocumentType | dt | JOIN | | UserFavorite | uf | LEFT JOIN | | Project | prj | LEFT JOIN | | Contract | cnt | LEFT JOIN | | Estimate | est | LEFT JOIN | | Department | dep | LEFT JOIN | | BaseObjectRead | bor | LEFT JOIN | | cut | — | LEFT JOIN | ## Custom Fields - Module: `Skill.Module.BusinessObjects.Bill` *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Brands URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-brands Summary: Extracts the list of brands. Extracts the list of brands. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Brands/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | ClientId | cli | Id | | Client | cli | Name | | BrandId | brd | Oid | | Brand | brd | Name | | ModifiedOn | brd | ModifiedOn | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Brand | brd | FROM | | ClientLookup | cli | JOIN | *Version: 4 · Category: Data Extraction · System: No* --- ## DE-BusinessObjectTypes URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-businessobjecttypes Summary: Extracts business object types. Extracts business object types. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-BusinessObjectTypes/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | BusinessObjectTypeId | bot | Oid | | BusinessObjectType | bot | Name | | Default | bot | Default | | Document | doc | Name | | DocumentId | doc | Oid | | HasConfiguration | — | iif(...) | ## Source Tables | Table | Alias | Join | |-------|-------|------| | BusinessObjectType | bot | FROM | | Document | doc | JOIN | ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Cities URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-cities Summary: Extracts all cities. Extracts all cities. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Cities/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | CityId | cit | Oid | | City | cit | Name | | CountryId | con | Oid | | Country | con | Name | ## Source Tables | Table | Alias | Join | |-------|-------|------| | City | cit | FROM | | Country | con | FROM | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Clients URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-clients Summary: Extracts the list of clients. Extracts the list of clients. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Clients/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | DocumentOid | cli | Oid | | ClientId | cli | Oid | | Client | cli | Name | | ExternalId | cli | ExternalId | | Code | cli | Code | | Email | cli | Email | | Phone | cli | Phone | | HeadOffice | cli | HeadOffice | | Street | cli | Street | | Street2 | cli | Street2 | | Location | cli | City | | CreatedOn | cli | CreatedOnUtc | | ModifiedOn | cli | ModifiedOnUtc | | AllowsTimesheet | cli | AllowsTimesheet | | ClientGroupId | clg | Oid | | ClientGroup | clg | Name | | TaxPayerNumber | cli | TaxPayerNumber | | Margin | cli | Margin | | FullTimeEmployeeTime | cli | FullTimeEmployeeTime | | SupplierMargin | cli | SupplierMargin | | StageId | wfs | Oid | | Stage | wfs | Name | | StageTypeId | wst | Oid | | StageType | wst | Name | | ManagerId | mng | Id | | ManagerName | mng | Name | | ManagerHasImage | mng | HasImage | | OwnerId | own | Id | | OwnerName | own | Name | | OwnerHasImage | own | HasImage | ## Source Tables | Table | Alias | Join | |-------|-------|------| | CommercialClient | cli | FROM | | ClientGroup | clg | LEFT JOIN | | WorkflowState | wfs | JOIN | | WorkflowStateType | wst | JOIN | | UserLookup | mng | LEFT JOIN | | UserLookup | own | LEFT JOIN | ## Custom Fields - Module: `Skill.Module.BusinessObjects.CommercialClient` ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 11 · Category: Data Extraction · System: No* --- ## DE-ClientsCompanies URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-clientscompanies Summary: Extracts the information about what companies have access to what clients. Extracts the information about what companies have access to what clients. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-ClientsCompanies/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | ClientId | cli | Oid | | Client | cli | Name | | CompanyId | com | Oid | | Company | com | Name | ## Source Tables | Table | Alias | Join | |-------|-------|------| | CommercialClient | cli | FROM | | CommercialClientCompany | ccc | LEFT JOIN | | Company | com | LEFT JOIN | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Comments URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-comments Summary: Extracts comments from the feed. Extracts comments from the feed. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Comments/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | CommentsId | — | Oid | | DocumentType | — | DocumentTypeName | | DocumentId | — | DocumentOid | | CreatedById | cre | Id | | CreatedBy | cre | Name | | CreatedByHasImage | cre | HasImage | | CreatedOnUtc | — | CreatedOnUtc | | ModifiedOnUtc | — | ModifiedOnUtc | | Text | — | Text | | IsVisibleToClient | — | IsVisibleToClient | | Actions | — | ActionsJson | | Reactions | — | ReactionsJson | | HasReplies | — | HasComments | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Post | cmt | FROM | | UserLookup | cre | JOIN | ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-CommentsReplies URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-commentsreplies Summary: Extracts replies of comments. Extracts replies of comments. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-CommentsReplies/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | ReplyId | rpl | Oid | | CommentsId | cmt | Oid | | DocumentId | cmt | DocumentOid | | DocumentType | cmt | DocumentTypeName | | CreatedById | cre | Id | | CreatedBy | cre | Name | | CreatedByHasImage | cre | HasImage | | Text | rpl | Text | | CreatedOnUtc | rpl | CreatedOnUtc | | ModifiedOnUtc | rpl | ModifiedOnUtc | | Reactions | rpl | ReactionsJson | | Mentions | rpl | MentionsJson | ## Source Tables | Table | Alias | Join | |-------|-------|------| | PostComment | rpl | FROM | | Post | cmt | JOIN | | UserLookup | cre | JOIN | ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Companies URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-companies Summary: Extracts the list of companies. Extracts the list of companies. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Companies/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Name | com | Name | | Code | com | Code | | Oid | com | Oid | | Company | com | Name | | CompanyId | com | Oid | | CompanyHasImage | com | HasImage | | Currency | cur | Name | | CurrencyId | cur | Oid | | TimesheetStart | com | TimesheetStart | | ResourceType | com | GanttChartResourceType | | ProjectArticle | com | ProjectArticle | | HoursType | com | HoursType | | RequiredHours | com | RequiredHours | | MarginType | com | MarginType | | Article | art | Name | | ArticleId | art | Oid | | CreatedOnUtc | com | CreatedOnUtc | | CreatedById | cre | Id | | CreatedBy | cre | Name | | CreatedByHasImage | cre | HasImage | | ModifiedOnUtc | com | ModifiedOnUtc | | ModifiedOn | com | ModifiedOnUtc | | ModifiedById | mod | Id | | ModifiedBy | mod | Name | | ModifiedByHasImage | mod | HasImage | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Company | com | FROM | | UserLookup | cre | JOIN | | UserLookup | mod | LEFT JOIN | | Article | art | LEFT JOIN | | Currency | cur | LEFT JOIN | *Version: 5 · Category: Data Extraction · System: Yes* --- ## DE-CompaniesAdditionalInformation URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-companiesadditionalinformation Summary: Extracts the custom fields associated with the companies. Extracts the custom fields associated with the companies. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-CompaniesAdditionalInformation/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | CompanyId | com | Oid | | Company | com | Name | | * | cuf | * | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Company | com | FROM | | Company_UserFields | cuf | LEFT JOIN | *Version: 3 · Category: Data Extraction · System: No* --- ## DE-Contracts URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-contracts Summary: Extracts contracts information. Extracts contracts information. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Contracts/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns Column metadata could not be extracted — the SQL statement could not be parsed automatically. ## Source Tables No table metadata detected. *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Countries URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-countries Summary: Extracts the list of countries. Extracts the list of countries. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Countries/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | CountryId | cou | Oid | | Country | cou | Name | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Country | cou | FROM | *Version: 3 · Category: Data Extraction · System: No* --- ## DE-Currencies URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-currencies Summary: Extracts the list of currencies. Extracts the list of currencies. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Currencies/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | CurrencyId | cur | Oid | | Currency | cur | Name | | IsoCode | cur | IsoCode | | Symbol | cur | Symbol | | ModifiedOn | cur | ModifiedOnUtc | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Currency | cur | FROM | *Version: 3 · Category: Data Extraction · System: No* --- ## DE-Departments URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-departments Summary: Extracts the list of departments. Extracts the list of departments. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Departments/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | CompanyId | com | Oid | | Company | com | Name | | DivisionId | div | Oid | | Division | div | Name | | DepartmentId | dep | Oid | | Department | dep | Name | | ModifiedOn | dep | ModifiedOnUtc | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Department | dep | FROM | | Division | div | JOIN | | Company | com | JOIN | *Version: 3 · Category: Data Extraction · System: No* --- ## DE-Descriptions URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-descriptions Summary: Extracts the different versions of the descriptions of documents. Extracts the different versions of the descriptions of documents. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Descriptions/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | DescriptionId | — | Oid | | Description | — | PlainText | | DescriptionHtml | — | Text | | Version | — | Version | | LatestVersion | — | (expression) | | IsLastVersion | — | iif(...) | | DocumentId | — | DocumentOid | | Document | — | DocumentTypeName | | CreatedOn | — | CreatedOn | | CreatedById | cre | Id | | CreatedBy | cre | Name | | ModifiedOn | des | EditedOn | ## Source Tables | Table | Alias | Join | |-------|-------|------| | DocumentBrief | des | FROM | | UserLookup | cre | JOIN | *Version: 2 · Category: Data Extraction · System: No* --- ## DE-Divisions URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-divisions Summary: Extracts the list of divisions. Extracts the list of divisions. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Divisions/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | CompanyId | com | Oid | | Company | com | Name | | DivisionId | div | Oid | | Division | div | Name | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Division | div | FROM | | Company | com | JOIN | *Version: 2 · Category: Data Extraction · System: No* --- ## DE-Employees URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-employees Summary: Extracts employees. Extracts employees. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Employees/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | EmployeeId | e | Oid | | Employee | e | Name | | Company | c | name | | CompanyId | c | Oid | | User | u | Name | | UserId | u | Oid | | ExternalId | e | ExternalId | | MaxValue | e | MaxValue | | Active | e | Active | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Employee | e | FROM | | User | u | LEFT JOIN | | Company | c | JOIN | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Estimates URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-estimates Summary: Extracts the list of estimates. Extracts the list of estimates. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Estimates/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns Column metadata could not be extracted — the SQL statement could not be parsed automatically. ## Source Tables No table metadata detected. ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 11 · Category: Data Extraction · System: No* --- ## DE-EstimatesBillingConditions URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-estimatesbillingconditions Summary: POST /api/v3/analytics/named-query/DE-EstimatesBillingConditions/dynamic-execute This query has no parameters. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-EstimatesBillingConditions/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | BillingConditionId | bic | Oid | | EstimateId | est | Oid | | Estimate | — | (expression) | | EstimateNumber | est | Number | | BillingClientId | bic | BillingClient | | BillingClient | bcl | NameAndExternalId | | Type | bic | Type | | Frequency | bic | Frequency | | PaymentCondition | pmc | Name | | PaymentConditionId | bic | PaymentCondition | | AmountType | bic | AmountType | | Percentage | bic | Percentage | | Value | bic | Value | | YourReference | bic | YourReference | | Date | bic | Date | | DayOfMonth | bic | DayOfMonth | | DayOfWeek | bic | DayOfWeek | | CompanyId | est | Company | | Company | com | Name | | ClientId | est | Client | | Client | cli | Name | ## Source Tables | Table | Alias | Join | |-------|-------|------| | BillingCondition | bic | FROM | | PaymentCondition | pmc | LEFT JOIN | | Client | bcl | JOIN | | Estimate | est | JOIN | | CommercialClient | cli | JOIN | | Company | com | JOIN | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-EstimatesCount URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-estimatescount Summary: Gets the count of estimates for the given filters. Gets the count of estimates for the given filters. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-EstimatesCount/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Count | — | (expression) | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Estimate | est | FROM | | WorkflowState | wfs | JOIN | | WorkflowStateType | wst | JOIN | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-EstimatesQuotes URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-estimatesquotes Summary: Extracts the estimate details. Extracts the estimate details. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-EstimatesQuotes/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | EstimateId | est | Oid | | Estimate | — | (expression) | | EstimateNumber | est | Number | | DepartmentId | dep | Id | | Department | dep | Name | | ModifiedOn | est | ModifiedOnUtc | | StageId | wfs | Oid | | Stage | wfs | Name | | ClientId | cli | Id | | Client | cli | Name | | Contract | — | (expression) | | ContractId | cnt | Id | | ProjectId | prj | Id | | Project | — | (expression) | | EstimateItemId | eit | Oid | | EstimateItem | eit | Name | | EstimateItemDescription | eit | Description | | EstimateItemDetailDescription | eid | Description | | SupplierId | sup | Oid | | Supplier | sup | Name | | ServiceId | art | Oid | | Service | art | Name | | EstimateItemDetailType | eid | Type | | EstimateItemDetailDepartmentId | ddp | Id | | EstimateItemDetailDepartment | ddp | Name | | EstimateItemDetailTypologyGroupId | eid | UserTypologyGroup | | EstimateItemDetailTypologyGroup | utg | Name | | EstimateItemDetailUserId | eid | User | | EstimateItemDetailUser | usr | Name | | ProductId | pro | Oid | | Product | pro | Name | | BrandId | brd | Oid | | Brand | brd | Name | | EstimateItemDetailId | eid | Oid | | CurrencyId | est | Currency | | Currency | cur | Name | | Exchange | est | Exchange | | EstimateItemServiceId | ari | Oid | | EstimateItemService | ari | Name | | EstimateItemRetainer | eit | Retainer | | EstimateItemQuantityIncome | eit | QuantityIncome | | EstimateItemValueWithoutVatIncome | eit | ValueWithoutVatIncome | | EstimateItemVatValueIncome | eit | VatValueIncome | | EstimateItemValueWithVatIncome | eit | ValueWithVatIncome | | EstimateItemClientDirectTotal | eit | ClientDirectTotal | | EstimateItemValueWithVatIncomeWithClientDirect | eit | ValueWithVatIncomeWithClientDirect | | EstimateItemDetailCost | — | (expression) | | EstimateItemDetailIncome | — | (expression) | | EstimateItemDetailTableRate | eid | TableRate | | EstimateItemDetailUnitPriceCost | eid | UnitPriceCost | | EstimateItemDetailUnitPriceIncome | — | (expression) | | DiscountCost | eid | DiscountCost | | QuantityCost | eid | QuantityCost | | ValueWithoutVatCost | eid | ValueWithoutVatCost | | VatValueCost | eid | VatValueCost | | ValueWithVatCost | eid | ValueWithVatCost | | DiscountIncome | eid | DiscountIncome | | QuantityIncome | eid | QuantityIncome | | AgencyCommissionValue | eid | AgencyCommissionValue | | ValueWithoutVatIncome | eid | ValueWithoutVatIncome | | Margin | eid | Margin | | MarginPercentage | eid | MarginPercentage | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Estimate | est | FROM | | EstimateItem | eit | JOIN | | EstimateItemDetail | eid | JOIN | | JobType | typ | JOIN | | WorkflowState | wfs | JOIN | | WorkflowStateType | wst | JOIN | | ClientLookup | cli | JOIN | | ProjectLookup | prj | LEFT JOIN | | ContractLookup | cnt | LEFT JOIN | | CommercialClientProduct | pro | LEFT JOIN | | Brand | brd | LEFT JOIN | | UserTypologyGroup | utg | LEFT JOIN | | Currency | cur | LEFT JOIN | | DepartmentLookup | dep | JOIN | | DepartmentLookup | ddp | LEFT JOIN | | UserLookup | usr | LEFT JOIN | | Supplier | sup | LEFT JOIN | | Article | art | LEFT JOIN | | Article | ari | LEFT JOIN | ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 8 · Category: Data Extraction · System: No* --- ## DE-EstimatesQuotesCount URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-estimatesquotescount Summary: Counts the occurrences of quotes. Counts the occurrences of quotes. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-EstimatesQuotesCount/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Count | — | (expression) | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Estimate | est | FROM | | EstimateItem | eit | JOIN | | EstimateItemDetail | eid | JOIN | | JobType | typ | JOIN | | WorkflowState | wfs | JOIN | | WorkflowStateType | wst | JOIN | | ClientLookup | cli | JOIN | | ProjectLookup | prj | LEFT JOIN | | ContractLookup | cnt | LEFT JOIN | | CommercialClientProduct | pro | LEFT JOIN | | Brand | brd | LEFT JOIN | | UserTypologyGroup | utg | LEFT JOIN | | Currency | cur | LEFT JOIN | | Department | dep | LEFT JOIN | | UserLookup | usr | LEFT JOIN | | Supplier | sup | LEFT JOIN | | Article | art | LEFT JOIN | | Article | ari | LEFT JOIN | ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-EstimatesQuotesMonth URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-estimatesquotesmonth Summary: Extracts all data from estimates. Extracts all data from estimates. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-EstimatesQuotesMonth/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | EstimateId | est | Oid | | Estimate | — | (expression) | | EstimateNumber | est | Number | | DepartmentId | dep | Id | | Department | dep | Name | | StageId | wfs | Oid | | Stage | wfs | Name | | ClientId | est | Client | | Client | cli | Name | | ProjectId | est | Project | | Project | — | (expression) | | EstimateItem | eit | Name | | EstimateItemDescription | eit | Description | | EstimateItemDetailDepartmentId | ddp | Id | | EstimateItemDetailDepartment | ddp | Name | | EstimateItemDetailTypologyGroupId | eid | UserTypologyGroup | | EstimateItemDetailTypologyGroup | utg | Name | | EstimateItemDetailUserId | eid | User | | EstimateItemDetailUser | usr | Name | | EstimateItemDetailDescription | eid | Description | | ProductId | est | Product | | Product | pro | Name | | EstimateItemDetailId | eid | Oid | | CurrencyId | est | Currency | | Currency | cur | Name | | Exchange | est | Exchange | | EstimateItemDetailTime | edm | Hours | | EstimateItemDetailCost | — | (expression) | | EstimateItemDetailIncome | — | (expression) | | EstimateItemDetailMonth | edm | DateUtc | | EstimateItemDetailTableRate | eid | TableRate | | EstimateItemDetailUnitPriceCost | eid | UnitPriceCost | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Estimate | est | FROM | | EstimateItem | eit | JOIN | | EstimateItemDetail | eid | JOIN | | EstimateItemDetailMonth | edm | LEFT JOIN | | JobType | typ | JOIN | | WorkflowState | wfs | JOIN | | WorkflowStateType | wst | JOIN | | CommercialClient | cli | JOIN | | Project | prj | LEFT JOIN | | CommercialClientProduct | pro | LEFT JOIN | | UserTypologyGroup | utg | JOIN | | Currency | cur | JOIN | | DepartmentLookup | dep | JOIN | | DepartmentLookup | ddp | LEFT JOIN | | User | usr | LEFT JOIN | ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 11 · Category: Data Extraction · System: No* --- ## DE-EstimatesQuotesMonthCount URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-estimatesquotesmonthcount Summary: Gets the count of estimate quotes for the given filters. Gets the count of estimate quotes for the given filters. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-EstimatesQuotesMonthCount/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns Column metadata could not be extracted — the SQL statement could not be parsed automatically. ## Source Tables No table metadata detected. *Version: 2 · Category: Data Extraction · System: No* --- ## DE-Expenses URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-expenses Summary: Extracts expenses for integration purposes. Extracts expenses for integration purposes. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Expenses/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | ExpenseId | eim | Oid | | ExpenseNumber | eim | Number | | Billable | eim | Billable | | Motive | eim | Motive | | ExpenseTypeId | eit | Oid | | ExpenseType | eit | Name | | Company | com | Name | | CompanyId | com | Id | | VatId | vat | Oid | | Vat | vat | Name | | VatPercentage | vat | Percentage | | ValueWithVat | eim | ValueWithVat | | VatValue | eim | VatValue | | ValueWithVat | eim | ValueWithVat | | CreatedOnUtc | eim | CreatedOnUtc | | ModifiedOnUtc | eim | ModifiedOnUtc | | CreatedByName | cre | Name | | ModifiedByName | mod | Name | | CreatedById | cre | Id | | ModifiedById | mod | Id | ## Source Tables | Table | Alias | Join | |-------|-------|------| | ExpenseItem | eim | FROM | | Expense | exp | LEFT JOIN | | ExpenseItemType | eit | JOIN | | CompanyLookup | com | JOIN | | Vat | vat | LEFT JOIN | | UserLookup | cre | LEFT JOIN | | UserLookup | mod | LEFT JOIN | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-ExpenseSheets URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-expensesheets Summary: Extracts expense sheets for integration purposes. Extracts expense sheets for integration purposes. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-ExpenseSheets/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | ExpenseSheetId | exp | Oid | | ExpenseSheet | exp | DocumentNumber | | ExpenseSheetNumber | exp | Number | | ExternalName | exp | ExternalName | | ExternalError | exp | ExternalError | | Emission | exp | Emission | | Due | exp | Due | | Exchange | exp | Exchange | | Blocked | exp | Blocked | | Paid | exp | Paid | | PaidValue | exp | PaidValue | | ValueWithVat | exp | ValueWithVat | | ValueWithoutVat | exp | ValueWithoutVat | | VatValue | exp | VatValue | | Company | com | Name | | CompanyId | com | Id | | CreatedOnUtc | exp | CreatedOnUtc | | ModifiedOnUtc | exp | ModifiedOnUtc | | CreatedByName | cre | Name | | ModifiedByName | mod | Name | | CreatedById | cre | Id | | ModifiedById | mod | Id | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Expense | exp | FROM | | CompanyLookup | com | JOIN | | UserLookup | cre | LEFT JOIN | | UserLookup | mod | LEFT JOIN | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-ExpenseType URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-expensetype Summary: Extracts expense items types. Extracts expense items types. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-ExpenseType/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | ExpenseTypeId | eit | Oid | | ExpenseType | eit | Name | | Company | com | Name | | CompanyId | com | Id | | Vat | vat | Name | | ExternalId | eit | ExternalId | | VatDeductiblePercentage | eit | VatDeductiblePercentage | | Value | eit | Value | | Active | eit | Active | | CreatedOnUtc | eit | CreatedOnUtc | | ModifiedOnUtc | eit | ModifiedOnUtc | | CreatedByName | cre | Name | | ModifiedByName | mod | Name | | CreatedById | cre | Id | | ModifiedById | mod | Id | ## Source Tables | Table | Alias | Join | |-------|-------|------| | ExpenseItemType | eit | FROM | | CompanyLookup | com | JOIN | | Vat | vat | LEFT JOIN | | UserLookup | cre | LEFT JOIN | | UserLookup | mod | LEFT JOIN | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-History URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-history Summary: Extract history of documents. Extract history of documents. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-History/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | HistoryId | hst | Oid | | DocumentType | hst | DocumentTypeName | | DocumentId | hst | DocumentOid | | Version | — | Version | | StartDate | hst | StartDate | | EndDate | hst | EndDate | | UserId | usr | Id | | User | usr | Name | | UserHasImage | usr | HasImage | | Action | — | Action | | StageId | wfs | Oid | | Stage | wfs | Name | | StageColor | wfs | Color | | StageTypeId | wst | Oid | | StageType | wst | Name | | StageTypeColor | wst | Color | | CreatedOnUtc | — | CreatedOnUtc | ## Source Tables | Table | Alias | Join | |-------|-------|------| | History | hst | FROM | | UserLookup | usr | JOIN | | WorkflowState | wfs | JOIN | | WorkflowStateType | wst | JOIN | ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Holidays URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-holidays Summary: Extracts the list of holidays. Extracts the list of holidays. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Holidays/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Day | hol | Date | | CompanyId | com | Oid | | Company | com | Name | | HolidayId | hol | Oid | | Holiday | hol | Name | | ModifiedOn | hol | ModifiedOn | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Holiday | hol | FROM | | Company | com | LEFT JOIN | *Version: 4 · Category: Data Extraction · System: No* --- ## DE-Jobs URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-jobs Summary: Extracts the list of jobs. Extracts the list of jobs. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Jobs/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | DocumentOid | job | Oid | | ClientId | cli | Id | | Client | cli | Name | | ClientHasImage | cli | HasImage | | ProjectId | prj | Id | | Project | prj | Name | | ProjectNumber | prj | Number | | JobId | job | Oid | | Job | job | Subject | | JobNumber | job | Number | | BusinessValue | job | BusinessValue | | ProductId | pro | Oid | | Product | pro | Name | | StageId | wfs | Oid | | Stage | wfs | Name | | StageColor | wfs | Color | | StageTypeId | wst | Oid | | StageType | wst | Name | | StageTypeColor | wst | Color | | TypeId | typ | Oid | | Type | typ | Name | | CompanyId | com | Id | | Company | com | Name | | CompanyHasImage | com | HasImage | | DivisionId | div | Id | | Division | div | Name | | DepartmentId | dep | Id | | Department | dep | Name | | StartDate | job | EntryDateUtc | | EndDate | job | AgreedDateUtc | | CreatedById | cre | Id | | CreatedBy | cre | Name | | CreatedByHasImage | cre | HasImage | | ModifiedId | mod | Id | | ModifiedBy | mod | Name | | ModifiedHasImage | mod | HasImage | | ModifiedOn | job | ModifiedOn | | AlreadyRead | — | iif(...) | | CurrentUserInTeam | — | iif(...) | | CurrentUserPending | — | iif(...) | | IsDelayed | — | iif(...) | | Delayed | — | iif(...) | | Version | job | Version | | Motive | his | Motive | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Deliverable | job | FROM | | UserLookup | cre | JOIN | | UserLookup | mod | JOIN | | ProjectLookup | prj | JOIN | | ClientLookup | cli | JOIN | | CommercialClientProduct | pro | LEFT JOIN | | WorkflowState | wfs | JOIN | | WorkflowStateType | wst | JOIN | | JobType | typ | JOIN | | DepartmentLookup | dep | JOIN | | DivisionLookup | div | JOIN | | CompanyLookup | com | JOIN | | cut | — | LEFT JOIN | | BaseObjectRead | bor | LEFT JOIN | | his | — | LEFT JOIN | ## Custom Fields - Module: `Skill.Module.BusinessObjects.Deliverable` ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 16 · Category: Data Extraction · System: No* --- ## DE-JobsCount URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-jobscount Summary: Gets the count of jobs for the given filters. Gets the count of jobs for the given filters. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-JobsCount/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Count | — | (expression) | ## Source Tables | Table | Alias | Join | |-------|-------|------| | JobLookup | job | FROM | | Deliverable | del | LEFT JOIN | | WorkflowState | wfs | JOIN | | WorkflowStateType | wst | JOIN | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Leaves URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-leaves Summary: Contains documents with information about vacations from employees #Description Contains documents with information about vacations from employees #Fields - CompanyId: unique identifier for the company (?string) - Company: name of the company (?string) - LeaveId: unique identifier for the leave (?string) - LeaveTypeId: unique identifier for the leave type (?string) - LeaveType: type of leave (?string - can be: 'Sick Leave', 'Vacation', 'Compensation') - UserId: unique identifier for the user (?string) - User: name of the user (?string) - Day: the date of the leave (?string, format yyyy-mm-ddTHH:MM:SS) - IsHalfDay: indicates if the leave is for half a day (bool) - Hours: leave duration in hours (int) - LeaveTypeYear: the year of the leave type (integer) - LeaveTypeExpiresOn: the date when the leave type expires (?string, format yyyy-mm-ddTHH:MM:SS) - ModifiedOn: date and time when the leave was last modified (?string, format yyyy-mm-ddTHH:MM:SS.SSS) - RequestedApproval: indicates if the leave was requested for approval (bool) - Status: status of the leave (?string - can be: 'New', 'Approved', 'Rejected') #Rules - If the user doesn't mention the year or month, assume the present. - If the user asks about a specific user, filter by the 'User' field. - If the user asks about a specific leave type, filter by the 'LeaveType' field. - If the user asks about a specific company, filter by the 'Company' field. - If the user asks about half-day leaves, filter by the 'IsHalfDay' field. - If the user asks about leaves within a specific date range, filter by the 'Day' field using `>=` and `<=` operators. - If the user doesn't specify a status, include all statuses. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Leaves/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | CompanyId | com | Id | | Company | com | Name | | LeaveId | lev | Oid | | LeaveTypeId | lvt | Oid | | LeaveType | lvt | Name | | UserId | usl | Id | | User | usl | Name | | Day | lev | Day | | IsHalfDay | lev | HalfDay | | Hours | — | iif(...) | | LeaveTypeYear | uiv | Year | | LeaveTypeExpiresOn | uiv | ExpirationDate | | ModifiedOn | lev | ModifiedOn | | RequestedApproval | lev | RequestedApproval | | Status | — | CASE(...) | | Approvers | apr | Approvers | | HRApprovers | hra | Approvers | ## Source Tables | Table | Alias | Join | |-------|-------|------| | UserVacation | lev | FROM | | UserInfoVacation | uiv | JOIN | | UserVacationType | lvt | JOIN | | UserLookup | usl | JOIN | | CompanyLookup | com | JOIN | | User | usr | JOIN | | apr | — | LEFT JOIN | | apr | hra | LEFT JOIN | *Version: 7 · Category: Data Extraction · System: Yes* --- ## DE-LeavesCount URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-leavescount Summary: POST /api/v3/analytics/named-query/DE-LeavesCount/dynamic-execute This query has no parameters. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-LeavesCount/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Count | — | (expression) | ## Source Tables | Table | Alias | Join | |-------|-------|------| | UserVacation | lev | FROM | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-LeavesDeleted URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-leavesdeleted Summary: Extracts deleted leaves using the parameter ModifiedFrom to filter data on the ModifiedOn field. Extracts deleted leaves using the parameter ModifiedFrom to filter data on the ModifiedOn field. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-LeavesDeleted/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | LeaveId | — | Oid | | ModifiedOnUtc | — | ModifiedOnUtc | ## Source Tables | Table | Alias | Join | |-------|-------|------| | LeaveDeleted | lev | FROM | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-LeavesDeletedCount URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-leavesdeletedcount Summary: Gets the count of deleted leaves for the filters provided. Gets the count of deleted leaves for the filters provided. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-LeavesDeletedCount/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Count | — | (expression) | ## Source Tables | Table | Alias | Join | |-------|-------|------| | LeaveDeleted | lev | FROM | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Products URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-products Summary: Extracts the list of products. Extracts the list of products. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Products/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | ClientId | cli | Id | | Client | cli | Name | | ProductId | pro | Oid | | Product | pro | Name | | BrandId | brd | Oid | | Brand | brd | Name | | ModifiedOn | pro | ModifiedOnUtc | ## Source Tables | Table | Alias | Join | |-------|-------|------| | CommercialClientProduct | pro | FROM | | ClientLookup | cli | JOIN | | Brand | brd | LEFT JOIN | *Version: 6 · Category: Data Extraction · System: No* --- ## DE-Projects URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-projects Summary: Extracts a list of projects. Extracts a list of projects. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Projects/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | DocumentOid | prj | Oid | | CompanyId | com | Id | | Company | com | Name | | CompanyHasImage | com | HasImage | | ClientId | cli | Id | | Client | cli | Name | | ClientHasImage | cli | HasImage | | ContractId | cnt | Id | | Contract | cnt | Name | | ContractNumber | cnt | Number | | ProjectId | prj | Oid | | Project | prj | Name | | ProjectNumber | prj | Number | | StartDate | prj | BeginDate | | EndDate | prj | EndDate | | ModifiedOn | prj | ModifiedOnUtc | | BrandId | brd | Oid | | Brand | brd | Name | | ProductId | pro | Oid | | Product | pro | Name | | ClassificationId | cls | Oid | | Classification | cls | Name | | NatureId | nat | Oid | | Nature | nat | Name | | StageId | wfs | Oid | | Stage | wfs | Name | | StageColor | wfs | Color | | StageTypeId | wst | Oid | | StageType | wst | Name | | StageTypeColor | wst | Color | | CurrencyId | cur | Oid | | Currency | cur | Name | | Investment | prj | Investment | | ProjectType | — | iif(...) | | RateCard | rtc | Name | | RateCardColumn | rcc | Name | | EstimatedWithoutTaxCost | — | isnull(...) | | EstimatedTaxCost | — | isnull(...) | | EstimatedWithTaxCost | — | isnull(...) | | EstimatedWithoutTaxSell | — | isnull(...) | | EstimatedTaxSell | — | isnull(...) | | EstimatedWithTaxSell | — | isnull(...) | | CreatedById | cre | Id | | CreatedBy | cre | Name | | CreatedByHasImage | cre | HasImage | | ModifiedId | mod | Id | | ModifiedBy | mod | Name | | ModifiedHasImage | mod | HasImage | | AlreadyRead | — | iif(...) | | CurrentUserInTeam | — | iif(...) | | CurrentUserPending | — | iif(...) | | IsDelayed | — | iif(...) | | Delayed | dld | Delayed | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Project | prj | FROM | | UserLookup | cre | JOIN | | UserLookup | mod | JOIN | | ContractLookup | cnt | LEFT JOIN | | CompanyLookup | com | JOIN | | ClientLookup | cli | JOIN | | CommercialClientProduct | pro | LEFT JOIN | | Brand | brd | LEFT JOIN | | ProjectClassification | cls | LEFT JOIN | | ProjectNature | nat | JOIN | | WorkflowState | wfs | JOIN | | WorkflowStateType | wst | JOIN | | Currency | cur | LEFT JOIN | | est | — | LEFT JOIN | | RateCard | rtc | LEFT JOIN | | RateCardColumn | rcc | LEFT JOIN | | cut | — | LEFT JOIN | | BaseObjectRead | bor | LEFT JOIN | | dld | — | LEFT JOIN | ## Custom Fields - Module: `Skill.Module.BusinessObjects.Project` ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 14 · Category: Data Extraction · System: No* --- ## DE-ProjectsAdditionalInformation URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-projectsadditionalinformation Summary: Extracts additional information from projects. Extracts additional information from projects. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-ProjectsAdditionalInformation/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | ProjectId | prj | Oid | | Project | prj | Name | | ProjectNumber | prj | Number | | * | puf | * | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Project | prj | FROM | | Project_UserFields | puf | LEFT JOIN | *Version: 4 · Category: Data Extraction · System: No* --- ## DE-ProjectsClassifications URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-projectsclassifications Summary: Extract project classifications. Extract project classifications. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-ProjectsClassifications/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | ProjectClassificationId | pcl | Oid | | ProjectClassification | pcl | Name | | Active | pcl | Active | | Billable | pcl | Billable | | Code | pcl | Code | | Default | pcl | Default | | Company | c | Name | | CompanyHasImage | c | HasImage | | CompanyId | c | Oid | ## Source Tables | Table | Alias | Join | |-------|-------|------| | ProjectClassification | pcl | FROM | | Company | c | LEFT JOIN | ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-ProjectsCount URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-projectscount Summary: Gets the count of projects for the provided filters. Gets the count of projects for the provided filters. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-ProjectsCount/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns Column metadata could not be extracted — the SQL statement could not be parsed automatically. ## Source Tables No table metadata detected. *Version: 1 · Category: Data Extraction · System: No* --- ## DE-ProjectsPlannedTime URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-projectsplannedtime Summary: Extract projects. Extract projects. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-ProjectsPlannedTime/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | ClientId | cli | Oid | | Client | cli | Name | | ProjectId | prj | Oid | | Project | — | (expression) | | ProjectNumber | prj | Number | | ProductId | pro | Oid | | Product | pro | Name | | ClassificationId | cls | Oid | | Classification | cls | Name | | NatureId | nat | Oid | | Nature | nat | Name | | DepartmentId | eid | Department | | Department | dep | Name | | ProjectPlannedUserTypologyGroupId | phd | UserTypologyGroup | | ProjectPlannedUserTypologyGroup | utg | Name | | ProjectPlannedUserId | phd | User | | ProjectPlannedUser | usr | Name | | EstimateItemDetailId | eid | Oid | | ProjectPlannedContractedTime | — | (expression) | | ProjectPlannedTime | — | (expression) | | ProjectPlannedIncome | — | (expression) | | Month | phd | Date | | ActualSellRate | pnh | SellRate | | ContractedSellRate | eid | TableRateSell | | RateCardSellRate | eid | TableRate | | Comments | pnh | Comments | | Description | pnh | Description | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Project | prj | FROM | | CommercialClient | cli | JOIN | | CommercialClientProduct | pro | LEFT JOIN | | ProjectClassification | cls | JOIN | | ProjectNature | nat | JOIN | | WorkflowState | wfs | JOIN | | WorkflowStateType | wst | JOIN | | PlannedHoursDeliverableTotal | pnh | JOIN | | PlannedHoursDeliverableAdjustment | phd | JOIN | | UserTypologyGroup | utg | JOIN | | User | usr | JOIN | | EstimateItemDetail | eid | JOIN | | EstimateItem | eit | JOIN | | Estimate | est | JOIN | | Department | dep | JOIN | | Division | div | JOIN | | Company | com | JOIN | *Version: 6 · Category: Data Extraction · System: No* --- ## DE-ProjectsPlannedTimeCount URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-projectsplannedtimecount Summary: Gets the count of projects planned time for the provided filters. Gets the count of projects planned time for the provided filters. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-ProjectsPlannedTimeCount/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns Column metadata could not be extracted — the SQL statement could not be parsed automatically. ## Source Tables No table metadata detected. *Version: 1 · Category: Data Extraction · System: No* --- ## DE-ProjectsTypes URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-projectstypes Summary: Extract projects types. Extract projects types. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-ProjectsTypes/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | DocumentOid | prt | Oid | | ProjectTypeId | prt | Oid | | ProjectType | prt | Name | | Company | com | name | | CompanyId | com | Oid | | CompanyHasImage | com | HasImage | | DocumentType | dct | Name | | TemplateFileName | prt | TemplateFileName | | AllowsTimesheet | prt | AllowsTimesheet | | IsDeliverable | prt | IsDeliverable | | Active | prt | Active | ## Source Tables | Table | Alias | Join | |-------|-------|------| | ProjectNature | prt | FROM | | Company | com | FROM | | DocumentType | dct | FROM | ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-PurchaseOrders URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-purchaseorders Summary: Extracts purchase orders data from the system. Extracts purchase orders data from the system. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-PurchaseOrders/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Oid | doc | Oid | | DocumentOid | doc | Oid | | Name | doc | Number | | Number | doc | Number | | Status | doc | Status | | FinancialStatus | doc | FinancialStatus | | CreatedOnUtc | doc | CreatedOnUtc | | CreatedById | doc | CreatedBy | | CreatedBy | usrCb | Name | | CreatedByHasImage | usrCb | HasImage | | ModifiedOnUtc | doc | ModifiedOnUtc | | ModifiedById | doc | ModifiedBy | | ModifiedBy | usrMb | Name | | ModifiedByHasImage | usrMb | HasImage | | StartDate | doc | Date | | DeliveryDate | doc | DeliveryDate | | Client | cc | Name | | ClientId | cc | Id | | ClientHasImage | cc | HasImage | | Department | d | Name | | ContractId | cnt | Id | | Contract | cnt | Name | | Project | — | (expression) | | ProjectId | p | Id | | Estimate | e | Name | | EstimateId | e | Oid | | Company | c | Name | | CompanyId | c | Id | | CompanyHasImage | c | HasImage | | Supplier | s | NameAndExternalId | | ValueWithoutVat | doc | ValueWithoutVat | | ValueWithVat | doc | ValueWithVat | | VatValue | doc | VatValue | | Invoiced | doc | Invoiced | | InvoicedValue | doc | InvoicedValue | | ControlledValue | doc | ControlledValue | | External | doc | External | | ExternalId | doc | ExternalId | | ExternalError | doc | ExternalError | | StageType | wst | Name | | Stage | — | isnull(...) | | Color | — | isnull(...) | | AlreadyRead | — | iif(...) | | CurrentUserInTeam | — | iif(...) | | CurrentUserPending | — | iif(...) | | CurrentUserInDepartment | — | iif(...) | | CurrencyIsoCode | curr | IsoCode | | Currency | curr | Name | | Articles | art | Articles | ## Source Tables | Table | Alias | Join | |-------|-------|------| | PurchaseOrder | doc | FROM | | ProjectLookup | p | LEFT JOIN | | ContractLookup | cnt | LEFT JOIN | | CompanyLookup | c | LEFT JOIN | | Estimate | e | LEFT JOIN | | DepartmentLookup | d | LEFT JOIN | | Currency | curr | LEFT JOIN | | ClientLookup | cc | LEFT JOIN | | Supplier | s | LEFT JOIN | | UserLookup | usrCb | LEFT JOIN | | UserLookup | usrMb | LEFT JOIN | | BaseObjectRead | bor | LEFT JOIN | | WorkflowState | ws | JOIN | | Configuration | cfg | JOIN | | UserLookup | usr | LEFT JOIN | | CompanyLookup | com | LEFT JOIN | | LocalizationLanguage | lol | LEFT JOIN | | Localization | loc | LEFT JOIN | | cut | — | LEFT JOIN | | WorkflowStateType | wst | JOIN | | art | — | LEFT JOIN | ## Custom Fields - Module: `Skill.Module.BusinessObjects.PurchaseOrder` ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-RateCardsColumns URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-ratecardscolumns Summary: Extraction of rate cards' columns. Extraction of rate cards' columns. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-RateCardsColumns/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | RateCardId | rtc | Oid | | RateCard | rtc | Name | | RateCardColumnId | rcc | Oid | | RateCardColumn | rcc | Name | | RateCardItemId | rci | Oid | | RateCardItemValueId | riv | Oid | | Active | rtc | Active | | StartDate | rtc | BeginDate | | EndDate | rtc | EndDate | | CurrencyId | cur | Oid | | Currency | cur | Name | | CompanyId | com | Oid | | Company | com | Name | | RateCardItemDepartmentId | dep | Oid | | RateCardItemDepartment | dep | Name | | RateCardItemTypologyGroupId | utg | Oid | | RateCardItemTypologyGroup | utg | Name | | RateCardItemUserId | usr | Oid | | RateCardItemUser | usr | Name | | Cost | riv | Cost | ## Source Tables | Table | Alias | Join | |-------|-------|------| | RateCard | rtc | FROM | | RateCardItem | rci | JOIN | | RateCardItemValue | riv | JOIN | | RateCardColumn | rcc | JOIN | | UserTypologyGroup | utg | JOIN | | User | usr | LEFT JOIN | | Department | dep | LEFT JOIN | | Company | com | LEFT JOIN | | Currency | cur | LEFT JOIN | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Requests URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-requests Summary: Extracts requests data. Extracts requests data. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Requests/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | DocumentOid | doc | Oid | | RequestId | doc | Oid | | Request | doc | Name | | RequestNumber | doc | Number | | BeginDateUtc | doc | BeginDateUtc | | EndDateUtc | doc | EndDateUtc | | CreatedOnUtc | doc | CreatedOnUtc | | ModifiedOnUtc | doc | ModifiedOnUtc | | Days | — | datediff(...) | | TagsJson | doc | TagsJson | | IsActivated | doc | IsActivated | | CreatedBy | usrCb | Name | | CreatedById | usrCb | Id | | CreatedByHasImage | usrCb | HasImage | | CreatedByTags | usrCb | TagsJson | | Company | c | Name | | CompanyId | c | Id | | CompanyHasImage | c | HasImage | | ClientGroup | clg | Name | | Client | cclu | Name | | ClientId | cclu | Id | | ClientHasImage | cclu | HasImage | | ClientClassification | ccl | Name | | Type | jt | Name | | TypeStyle | jt | StyleJson | | Product | ccp | Name | | Brand | brd | Name | | Contract | con | Name | | ContractId | con | Id | | Stage | — | isnull(...) | | StageColor | — | isnull(...) | | ModifiedBy | usrMb | Name | | ModifiedById | usrMb | Id | | ModifiedByHasImage | usrMb | HasImage | | IsDraft | doc | IsDraft | | CreatedByCompanyId | uc | Id | | CreatedByCompany | uc | Name | | CreatedByCompanyHasImage | uc | HasImage | | StageType | wst | Name | | AlreadyRead | — | iif(...) | | CurrentUserInTeam | — | iif(...) | | BaseObjectReadId | bor | Oid | | FavoriteId | uf | Oid | | IsFavorite | — | iif(...) | | Workflow | wkf | Name | | Priority | doc | Priority | | Version | doc | Version | | Department | dep | Name | | DepartmentId | dep | Id | | Division | div | Name | | DivisionId | div | Id | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Request | doc | FROM | | UserFavorite | uf | LEFT JOIN | | UserLookup | usrMb | LEFT JOIN | | CompanyLookup | c | LEFT JOIN | | Clientlookup | cclu | LEFT JOIN | | ClientGroup | clg | LEFT JOIN | | ClientClassification | ccl | LEFT JOIN | | JobType | jt | LEFT JOIN | | DepartmentLookup | dep | LEFT JOIN | | DivisionLookup | div | LEFT JOIN | | CommercialClientProduct | ccp | LEFT JOIN | | Brand | brd | LEFT JOIN | | UserLookup | usrCb | LEFT JOIN | | CompanyLookup | uc | LEFT JOIN | | ContractLookup | con | LEFT JOIN | | WorkflowState | ws | JOIN | | Configuration | cfg | JOIN | | UserLookup | usr | LEFT JOIN | | CompanyLookup | com | LEFT JOIN | | LocalizationLanguage | lol | LEFT JOIN | | Localization | loc | LEFT JOIN | | Currency | curr | LEFT JOIN | | DocumentType | wkf | JOIN | | cut | — | LEFT JOIN | | BaseObjectRead | bor | LEFT JOIN | | WorkflowStateType | wst | JOIN | ## Custom Fields - Module: `Skill.Module.BusinessObjects.Request` *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Services URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-services Summary: Extracts the existing services. Extracts the existing services. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Services/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Oid | a | Oid | | ServiceId | a | Oid | | Service | a | Name | | Company | c | Name | | CompanyId | c | Oid | | CompanyHasImage | c | HasImage | | Active | a | Active | | InternalService | a | InternalService | | DepartmentRequired | a | DepartmentRequired | | UnitHour | a | UnitHour | | DefaultMargin | a | DefaultMargin | | ExternalId | a | ExternalId | | VatDeductiblePercentage | a | VatDeductiblePercentage | | Unit | a | Unit | | ServiceGroupId | ag | Oid | | ServiceGroup | ag | Name | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Article | a | FROM | | Company | c | JOIN | | ArticleGroup | ag | LEFT JOIN | *Version: 2 · Category: Data Extraction · System: Yes* --- ## DE-ServicesGroups URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-servicesgroups Summary: Extracts the services groups. Extracts the services groups. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-ServicesGroups/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Oid | ag | Oid | | ServiceGroupId | ag | Oid | | ServiceGroup | ag | Name | | Company | c | Name | | CompanyId | c | Oid | | CompanyHasImage | c | HasImage | ## Source Tables | Table | Alias | Join | |-------|-------|------| | ArticleGroup | ag | FROM | | Company | c | JOIN | *Version: 2 · Category: Data Extraction · System: Yes* --- ## DE-Stages URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-stages Summary: Extracts the list of stages of the workflows. Extracts the list of stages of the workflows. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Stages/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | StageId | wfs | Oid | | Stage | wfs | Name | | TypeId | wst | Oid | | Type | wst | Name | ## Source Tables | Table | Alias | Join | |-------|-------|------| | WorkflowState | wfs | FROM | | WorkflowStateType | wst | JOIN | *Version: 2 · Category: Data Extraction · System: No* --- ## DE-Suppliers URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-suppliers Summary: Extracts suppliers for integration purposes. Extracts suppliers for integration purposes. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Suppliers/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | DocumentOid | s | Oid | | SupplierId | s | Oid | | Supplier | s | Name | | Company | com | Name | | CompanyId | com | Id | | Division | d | Name | | DivisionId | d | Oid | | Department | dp | Name | | DepartmentId | dp | Oid | | Currency | cr | Name | | CurrencyId | cr | Oid | | VatId | v | Oid | | Vat | v | Name | | ExternalId | s | ExternalId | | IsActive | s | Active | | PaymentConditionId | pc | Oid | | PaymentCondition | pc | Name | | Category | s | Category | | CreatedById | createdBy | Id | | CreatedBy | createdBy | Name | | ModifiedById | modifiedBy | Id | | ModifiedBy | modifiedBy | Name | | CreatedOnUtc | s | CreatedOnUtc | | ModifiedOnUtc | s | ModifiedOnUtc | | Mail | s | Mail | | Remarks | s | Remarks | | DiscountPercentage | s | DiscountPercentage | | VolumeDiscountPercentage | s | VolumeDiscountPercentage | | OtherCreditor | s | OtherCreditor | | Street | s | Street | | TaxPayerNumber | s | TaxPayerNumber | | RelatedDepartment | depRelated | Name | | RelatedDepartmentId | depRelated | Oid | | RelatedCompany | companyRelated | Name | | RelatedCompanyId | companyRelated | Oid | | Country | country | Name | | City | city | Name | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Supplier | s | FROM | | CompanyLookup | com | JOIN | | Division | d | LEFT JOIN | | Department | dp | LEFT JOIN | | Department | depRelated | LEFT JOIN | | Company | companyRelated | LEFT JOIN | | Currency | cr | LEFT JOIN | | Vat | v | LEFT JOIN | | PaymentCondition | pc | LEFT JOIN | | UserLookup | createdBy | LEFT JOIN | | UserLookup | modifiedBy | LEFT JOIN | | Country | country | LEFT JOIN | | City | city | LEFT JOIN | ## Custom Fields - Module: `Skill.Module.BusinessObjects.Supplier` ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | | SupplierRead | No | | Base | No | *Version: 2 · Category: Data Extraction · System: No* --- ## DE-Taxes URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-taxes Summary: Extracts information about taxes. Extracts information about taxes. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Taxes/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | CompanyId | com | Id | | Company | com | Name | | CompanyHasImage | com | HasImage | | TaxId | vat | Oid | | Tax | vat | Name | | Percentage | vat | Percentage | | IsActive | vat | Active | | ExternalId | vat | ExternalId | | Default | vat | Default | ## Source Tables | Table | Alias | Join | |-------|-------|------| | vat | — | FROM | | CompanyLookup | com | JOIN | ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-TimeSheets URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-timesheets Summary: Extracts the time entered in time sheets. Extracts the time entered in time sheets. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-TimeSheets/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | TimesheetId | tim | oid | | UserId | usl | Id | | User | usl | Name | | UserCompanyId | ucm | Id | | UserCompany | ucm | Name | | UserDepartmentId | dep | Id | | UserDepartment | dep | Name | | UserEmail | usl | Mail | | TypologyId | utg | Oid | | Typology | utg | Name | | Day | tim | Date | | Hours | — | (expression) | | ClientId | cli | Id | | Client | cli | Name | | ProjectId | prj | Id | | Project | prj | Name | | ProjectNumber | prj | Number | | JobId | job | Id | | Job | job | Name | | JobNumber | job | Number | | JobType | typ | Name | | IsBillable | — | iif(...) | | CompanyId | com | Id | | Company | com | Name | | ProductId | prd | Oid | | Product | prd | Name | | ProductCode | prd | Code | | ProductExternalId | prd | ExternalId | | BrandId | brd | Oid | | Brand | brd | Name | | WorkTypeId | wrk | Oid | | WorkType | wrk | Name | | Status | — | CASE(...) | | Approvers | — | isnull(...) | | ModifiedOn | tim | ModifiedOn | | RequestedApproval | tim | RequestedApproval | | HourlyUserCost | — | HourlyUserCost | | TotalUserCost | — | TotalUserCost | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Timesheet | tim | FROM | | JobLookup | job | LEFT JOIN | | ProjectLookup | prj | LEFT JOIN | | UserLookup | usl | JOIN | | CompanyLookup | com | JOIN | | CompanyLookup | ucm | JOIN | | WorkType | wrk | LEFT JOIN | | ClientLookup | cli | LEFT JOIN | | CommercialClientProduct | prd | LEFT JOIN | | Brand | brd | LEFT JOIN | | DepartmentLookup | dep | JOIN | | UserTypology | utg | JOIN | | JobType | typ | LEFT JOIN | | tap | — | LEFT JOIN | | UserLookup | apr | LEFT JOIN | *Version: 19 · Category: Data Extraction · System: No* --- ## DE-TimeSheetsCount URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-timesheetscount Summary: Gets the count of time sheets for the filters provided. Gets the count of time sheets for the filters provided. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-TimeSheetsCount/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns Column metadata could not be extracted — the SQL statement could not be parsed automatically. ## Source Tables No table metadata detected. *Version: 1 · Category: Data Extraction · System: No* --- ## DE-TimeSheetsDeleted URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-timesheetsdeleted Summary: Extracts time sheets that have been deleted. Extracts time sheets that have been deleted. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-TimeSheetsDeleted/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | TimesheetId | — | Oid | | ModifiedOnUtc | — | ModifiedOnUtc | ## Source Tables | Table | Alias | Join | |-------|-------|------| | TimesheetDeleted | tim | FROM | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-TimeSheetsDeletedCount URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-timesheetsdeletedcount Summary: Gets the count of deleted time sheet for the provided filters. Gets the count of deleted time sheet for the provided filters. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-TimeSheetsDeletedCount/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Count | — | (expression) | ## Source Tables | Table | Alias | Join | |-------|-------|------| | TimesheetDeleted | tim | FROM | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Transitions URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-transitions Summary: Extracts the list of existing transitions. Extracts the list of existing transitions. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Transitions/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Oid | wt | Oid | | TransitionId | wt | Oid | | Transition | wt | Name | | Document | doc | Name | | DocumentId | doc | Oid | | Workflow | dty | Name | | WorkflowId | dty | Oid | | FromWorkflowState | fws | Name | | FromWorkflowStateId | fws | Oid | | ToWorkflowState | tws | Name | | ToWorkflowStateId | tws | Oid | | ExternalId | wt | ExternalId | | Order | wt | Order | | RequestConfirmation | wt | RequestConfirmation | | MustSendNotification | wt | MustSendNotification | | CommentRequired | wt | CommentRequired | | HoursRequired | wt | HoursRequired | | FileUploadRequired | wt | FileUploadRequired | | FileUploadFolder | wt | FileUploadFolder | | QueryValidation | wt | QueryValidation | | Motives | mot | Motives | | Actions | act | Actions | | FromAllowWriteTeams | fpr | Teams | | ToAllowWriteTeams | tpr | Teams | | Roles | rol | Roles | | TypeIds | typ | TypeIds | | Types | typ | Types | ## Source Tables | Table | Alias | Join | |-------|-------|------| | WorkflowStateTransition | wt | FROM | | WorkflowState | fws | LEFT JOIN | | WorkflowState | tws | LEFT JOIN | | Document | doc | JOIN | | DocumentType | dty | JOIN | | typ | — | LEFT JOIN | | mot | — | LEFT JOIN | | act | — | LEFT JOIN | | pro | fpr | LEFT JOIN | | pro | tpr | LEFT JOIN | | rol | — | LEFT JOIN | ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Types URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-types Summary: Extracts job types. Extracts job types. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Types/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | TypeId | j | Oid | | DocumentOid | j | Oid | | Type | j | Name | | Code | j | Code | | DurationDays | j | DurationDays | | Active | j | Active | | IsRetainer | j | IsRetainer | | Plannable | j | Plannable | | IsDeliverable | j | IsDeliverable | | AllowAllJobTypes | j | AllowAllJobTypes | | CreatedOn | j | CreatedOn | | ModifiedOn | j | ModifiedOn | | BriefingTemplate | bt | Name | | BriefingTemplateId | bt | Oid | | BusinessObjectType | bot | Name | | BusinessObjectTypeId | bot | Oid | | Company | c | Name | | CompanyId | c | Oid | | Division | v | Name | | DivisionId | v | Oid | | Department | d | Name | | DepartmentId | d | Oid | | Document | doc | Name | | DocumentId | doc | Oid | | Workflow | w | Name | | WorkflowId | w | Oid | | CreatedByName | u | Name | | ModifiedByName | us | Name | | CreatedById | u | Id | | ModifiedById | us | Id | | CreatedByHasImage | u | HasImage | | ModifiedByHasImage | us | HasImage | | TypeStyle | j | StyleJson | | AccessibleToAllDepartments | j | AccessibleToAllDepartments | | AllowsTimesheet | j | AllowsTimesheet | | ServiceId | ar | Oid | | Service | ar | Name | | WorkType | wt | Name | | WorkTypeId | wt | Oid | ## Source Tables | Table | Alias | Join | |-------|-------|------| | JobType | j | FROM | | Department | d | LEFT JOIN | | Company | c | LEFT JOIN | | Division | v | LEFT JOIN | | Document | doc | LEFT JOIN | | DocumentType | w | LEFT JOIN | | BusinessObjectType | bot | LEFT JOIN | | BriefingTemplate | bt | LEFT JOIN | | UserLookup | u | LEFT JOIN | | UserLookup | us | LEFT JOIN | | Article | ar | LEFT JOIN | | WorkType | wt | LEFT JOIN | ## Custom Fields - Module: `Skill.Module.BusinessObjects.JobType` ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Typologies URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-typologies Summary: Extracts the list of typologies of users. Extracts the list of typologies of users. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Typologies/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | DocumentOid | utp | Oid | | TypologyId | utp | Oid | | Typology | utp | Name | | TypologyGroupId | utg | Oid | | TypologyGroup | utg | Name | | CompanyId | com | Id | | Company | com | Name | | CompanyHasImage | com | HasImage | | DivisionId | div | Id | | Division | div | Name | | DepartmentId | dep | Id | | Department | dep | Name | | Plannable | utp | Plannable | | IsActive | utp | Active | | HourlyValue | utp | HourlyValue | ## Source Tables | Table | Alias | Join | |-------|-------|------| | UserTypology | utp | FROM | | UserTypologyGroup | utg | LEFT JOIN | | CompanyLookup | com | LEFT JOIN | | DepartmentLookup | dep | LEFT JOIN | | DivisionLookup | div | LEFT JOIN | ## Custom Fields - Module: `Skill.Module.BusinessObjects.UserTypology` *Version: 4 · Category: Data Extraction · System: Yes* --- ## DE-TypologyGroups URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-typologygroups Summary: Extracts user typology groups of user typologies. Extracts user typology groups of user typologies. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-TypologyGroups/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | TypologyGroupId | utg | Oid | | TypologyGroup | utg | Name | | CompanyId | com | Oid | | Company | com | Name | ## Source Tables | Table | Alias | Join | |-------|-------|------| | UserTypologyGroup | utg | FROM | | Company | com | JOIN | *Version: 3 · Category: Data Extraction · System: No* --- ## DE-TypologyGroupsCompanies URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-typologygroupscompanies Summary: Extracts typology grous associated to companies Extracts typology grous associated to companies ## Endpoint ``` POST /api/v3/analytics/named-query/DE-TypologyGroupsCompanies/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Id | tgd | Oid | | TypologyGroupId | utg | Oid | | TypologyGroup | utg | Name | | CompanyId | com | Id | | Company | com | Name | ## Source Tables | Table | Alias | Join | |-------|-------|------| | UserTypologyGroupCompany | tgd | FROM | | CompanyLookup | com | JOIN | | UserTypologyGroup | utg | JOIN | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-TypologyGroupsDepartments URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-typologygroupsdepartments Summary: Extracts typology groups associated to departments. Extracts typology groups associated to departments. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-TypologyGroupsDepartments/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | Id | tgd | Oid | | TypologyGroupId | utg | Oid | | TypologyGroup | utg | Name | | DepartmentId | dep | Id | | Department | dep | Name | ## Source Tables | Table | Alias | Join | |-------|-------|------| | UserTypologyGroupDepartment | tgd | FROM | | DepartmentLookup | dep | JOIN | | UserTypologyGroup | utg | JOIN | *Version: 1 · Category: Data Extraction · System: Yes* --- ## DE-UserCosts URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-usercosts Summary: Extracts cost of users. Extracts cost of users. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-UserCosts/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | UserId | usr | Oid | | User | usr | Name | | MonthlyValue | umv | MonthlyValue | | HourlyValue | umv | HourlyValue | | StartDate | umv | StartDate | | EndDate | umv | EndDate | | CompanyId | com | Oid | | Company | com | Name | | CurrencyId | cur | Oid | | Currency | cur | Name | | CreatedOn | umv | CreatedOnUtc | | ModifiedOn | umv | ModifiedOnUtc | ## Source Tables | Table | Alias | Join | |-------|-------|------| | UserMonthlyValue | umv | FROM | | User | usr | FROM | | Company | com | FROM | | Currency | cur | FROM | *Version: 2 · Category: Data Extraction · System: No* --- ## DE-Users URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-users Summary: Extracts the list of users. Extracts the list of users. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Users/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | DocumentOid | usr | Oid | | UserId | usr | Oid | | User | usr | Name | | IsActive | usl | IsActive | | DepartmentId | dep | Oid | | Department | dep | Name | | DivisionId | div | Oid | | Division | div | Name | | CompanyId | com | Oid | | Company | com | Name | | TypologyId | utp | Oid | | Typology | utp | Name | | TypeId | ust | Oid | | Type | ust | Name | | CountryId | cou | Oid | | Country | cou | Name | | HireDate | usr | HireDate | | TerminationDate | usr | ExpirationDate | | InactivatedOnUtc | usl | InactivatedOnUtc | | Email | usr | Mail | | RequiredHours | usr | RequiredHours | | CompanyRequiredHours | com | RequiredHours | | HourlyValue | usr | HourlyValue | | CityId | usr | City | | ModifiedOn | usr | ModifiedOn | | TaxPayerNumber | usr | TaxPayerNumber | | ExternalId | usr | ExternalId | | IsClient | usr | IsClient | | ClientIds | cli | ClientIds | | Clients | cli | Clients | ## Source Tables | Table | Alias | Join | |-------|-------|------| | User | usr | FROM | | Department | dep | JOIN | | Division | div | JOIN | | Company | com | JOIN | | UserTypology | utp | JOIN | | UserType | ust | LEFT JOIN | | UserLookup | usl | JOIN | | Country | cou | LEFT JOIN | | cli | — | LEFT JOIN | ## Access | Role | Administrative | |------|---------------| | Administrator | Yes | *Version: 14 · Category: Data Extraction · System: No* --- ## DE-UsersAdditionalInformation URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-usersadditionalinformation Summary: POST /api/v3/analytics/named-query/DE-UsersAdditionalInformation/dynamic-execute This query has no parameters. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-UsersAdditionalInformation/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | UserId | usr | Oid | | User | usr | Name | | * | puf | * | ## Source Tables | Table | Alias | Join | |-------|-------|------| | User | usr | FROM | | User_UserFields | puf | LEFT JOIN | *Version: 2 · Category: Data Extraction · System: No* --- ## DE-UserTypes URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-usertypes Summary: Extracts the user types. Extracts the user types. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-UserTypes/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | UserTypeId | ust | Oid | | UserType | ust | Name | ## Source Tables | Table | Alias | Join | |-------|-------|------| | UserType | ust | FROM | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-Workloads URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-workloads Summary: Extracts data from Workloads. Extracts data from Workloads. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-Workloads/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | WorkloadId | dw | Oid | | DayUtc | dw | DayUtc | | Workload | dw | Workload | | JobId | dw | DocumentOid | | TimesheetId | dwt | Timesheet | | UserIs | usr | Id | | User | usr | Name | | ClientId | cli | Oid | | Client | cli | Name | | ProjectId | prj | Oid | | Project | — | (expression) | | JobId | job | Oid | | Job | job | NameAndExternalId | ## Source Tables | Table | Alias | Join | |-------|-------|------| | DailyWorkload | dw | FROM | | DailyWorkloadTimesheet | dwt | LEFT JOIN | | AssignmentType | ast | JOIN | | UserLookup | usr | JOIN | | Deliverable | job | JOIN | | Project | prj | JOIN | | CommercialClient | cli | JOIN | *Version: 1 · Category: Data Extraction · System: No* --- ## DE-WorkTypes URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/de-worktypes Summary: Extracts the work types list. Extracts the work types list. ## Endpoint ``` POST /api/v3/analytics/named-query/DE-WorkTypes/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | WorkTypeId | wrk | Oid | | WorkType | wrk | Name | | CompanyId | com | Oid | | Company | com | Name | ## Source Tables | Table | Alias | Join | |-------|-------|------| | WorkType | wrk | FROM | | Company | com | LEFT JOIN | *Version: 4 · Category: Data Extraction · System: No* --- ## Definition URL: https://documentation.skillsworkflow.com/docs/build-and-extend/workspaces/definition Summary: On this page you will find how to edit the workspaces. On this page you will find how to edit the workspaces. To have access to the these options, you need to click in the Edit workspace to open the workspace configuration. --- ## Parameters Example 1. Choose the parameters tab and insert the parameter name and value. 2. Add the created parameter in the query. --- ## Translations In this section you will find how to translate the terms of your workspace that don't exist in the system by default. Properties Type Required Description Language String false Select the language you want to translate the field. Term String false Expression to translate. Translation String false Translated term. Example --- ## About In this section you will find how to update the workspace to the version that you want. Properties Description Days Ago Days that elapsed since the published of that version.. Modified By The last person that modified the workspace. Description Description about what was done in the workspace. Actions Button to update the version of the workspace. # In the Version section you have three colors: - Green: Indicates the current version of the workspace, - Yellow: Shows a higher version of the current version workspace, - Grey: Shows a below version of the workspace. ::: Example --- ## Document URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/document Summary: With this namespace, you can quickly provide methods to manipulate documents. With this namespace, you can quickly provide methods to manipulate documents. The namespace Document provides to developers, methods to easily create, update, retrieve document data. ```javascript //accessing to Document methods SW.Document.{methodName} ``` --- ## create #### Description This method can be used to create a new document. #### Method(s) ```javascript function create( documentName: string, component: dxForm, params: { onClick?: (dashboardDocumentSaveObject: DashboardDocumentSaveObject) => boolean, components?: { description?: dxHtmlEditor, files?: FileSystemWidgetComponent }, mappers?: { postModel?: ( postModel: PostModel, dashboardDocumentSaveObject: DashboardDocumentSaveObject, params: { isDraftModel: boolean } ) => PostModel, briefPostModel: ( briefPostModel: BriefPostModel, dashboardDocumentSaveObject: DashboardDocumentSaveObject ) => BriefPostModel }, postChangesOnFeed?: boolean, allowDraft?: boolean, openAfterCreation?: boolean, icons?: { save?: { class?: string, tooltip?: string }, draft?: { class?: string, tooltip?: string } } }): ``` Parameter Type Required Defaults Description documentName DocumentName true Document's type name component dxForm true Document data #### Basic Usage ```javascript SW.Document.create(SW.DocumentName.Job, workspaceContext.get('form'), { allowDraft: false, components: { description: workspaceContext.get('description'), files: workspaceContext.get('files') }, postChangesOnFeed: false, onClick: async (dashboardDocumentSaveObject) => { SW.UI.Buttons.setAllEnabled(true); e.component.option('text', 'SAVE'); e.component.option('icon', ''); e.component.option('disabled', false); SW.UI.Alert.success('Changes Saved') return true; }, mappers: { briefPostModel: async (briefPostModel, dashboardDocumentSaveObject) => { var formData = dashboardDocumentSaveObject.Components.FormComponent.option('formData'); briefPostModel.Text = formData.Description return briefPostModel }, postModel: async (dashboardDocumentSaveObject) => { let form = workspaceContext.get('form') let formData = form.option('formData'); var executor = formData.ExecutorId; if (SW.Utils.isValidGuid(executor)) { dashboardDocumentSaveObject.Actions.Assignments = [ { Assign: true, UserId: executor, AssignmentTypeId: "31169ed9-b84d-4e94-87d4-048130fbd053" } ] } dashboardDocumentSaveObject.Actions.Document.Job.AgreedDateUtc = formData.AgreedDateUtc; return dashboardDocumentSaveObject } } }) ``` --- ## getCustomFields #### Description This method can be used to get a custom user field from various documents. #### Method(s) ```javascript 1 declare function getCustomFields( 2 documentName: DocumentName, 3 documentIds: string[], 4 userFieldName: string, 5 valueType: string 6 ): Promise; ``` Parameter Type Required Defaults Description documentName DocumentName true Document's type documentIds string[] true An array of document ids userFieldName string true User field name valueType string true Specify the value type of the document user field #### Basic Usage ```javascript SW.Document.getCustomFields( SW.DocumentName.Job, ["b983e9b5-b2b8-485f-8ff8-794463771bcc"], "Default", "string" ); ``` --- ## getLookup #### Description This method can be used to execute a document lookup. #### Method(s) ```javascript 1 declare function getLookup( 2 documentName: DocumentName, 3 options: string | {searchValue?: string, skip?: number, take?: number} = {} 4 ): Promise ``` Parameter Type Required Defaults Description document DocumentName true Document type options string false Document id or search, skip and take values #### Basic Usage ```javascript SW.Document.getLookup(SW.DocumentName.Job, options); ``` --- ## setCustomFields #### Description This method can be used to set custom user fields in documents. #### Method(s) ```javascript 1 declare function setCustomFields( 2 documentName: DocumentName, 3 documentIds: string[], 4 documentUserFieldsValue: DocumentUserFieldValueModel[] 5 ): Promise ``` Parameter Type Required Defaults Description documentName DocumentName true Document's type documentIds string[] true An array of document ids documentUserFieldsValue DocumentUserFieldValueModel[] true User fields to set into the passed documents #### Basic Usage ```javascript SW.Document.setCustomFields( SW.DocumentName.Job, ["b1dd37dd-4633-4cc4-a418-0830d5e35638"], [{ ColumnName: 'AddedOn', Value: false, ColumnDataTypeId: 0 }] ); ``` --- ## update #### Description This method can be used to update fields in a document. #### Method(s) ```javascript 1 declare function update( 2 documentName: DocumentName, 3 documentId: string, 4 fields: string[], 5 values: string[] 6 ): Promise ``` Parameter Type Required Defaults Description documentName DocumentName true Document type documentId string true Document id fields string[] true Fields to update values string[] true Values to update the fields #### Basic Usage ```javascript SW.updateDocument( SW.DocumentName.Job, "b1dd37dd-4633-4cc4-a418-0830d5e35638", ['AgreedDateUtc'], ['2021-01-01'] ); ``` --- ## Edit Layout URL: https://documentation.skillsworkflow.com/docs/build-and-extend/workspaces/edit-layout Summary: On this page you will find how to customize the layout of the workspace. ### Description On this page you will find how to customize the layout of the workspace. This option allows the user to change the size and position of the panels in the grid. To have access to the this option, you need to click in the Edit Layout. ### Example #### Before #### After --- ## Endpoint URL: https://documentation.skillsworkflow.com/docs/build-and-extend/workspaces/panels/datasource-endpoint Summary: On this page you will find how to create a workspace using an Endpoint as DataSource Basic Usage Example On this page you will find how to create a workspace using an Endpoint as DataSource Basic Usage ```js function returnEndpoint(mapper) { var clientId = SW.Application.Workspace.context().currentDocument.Oid; return SW.executeAPI( "GET", "v3/commercial-clients/" + clientId + "/requests/new" ).then((result) => { return mapper(result.Request); }); } ``` Example --- ## Estimate URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/document/document-estimate Summary: A sub namespace of Document, exclusive for estimate operations --- Get Custom Fields Get Lookup Set Custom Fields Update A sub namespace of Document, exclusive for estimate operations --- The same methods that are presented in the Document Introduction but do not take the first param documentName, because you're already in a Estimate document [Get Custom Fields](./#getcustomfields) [Get Lookup](./#getlookup) [Set Custom Fields](./#setcustomfields) [Update](./#update) --- ## EstimatedPlannedActualMonthly URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/data-extraction/estimatedplannedactualmonthly Summary: System generic extraction of estimated, planned and actual, per currency, including time, costs, income, profit. System generic extraction of estimated, planned and actual, per currency, including time, costs, income, profit. ## Endpoint ``` POST /api/v3/analytics/named-query/EstimatedPlannedActualMonthly/dynamic-execute ``` ## Parameters This query has no parameters. ## Output Columns | Column | Source Table | Source Column | |--------|-------------|---------------| | CompanyId | com | Oid | | Company | com | Name | | CompanyHasImage | com | HasImage | | Division | div | Name | | Department | dep | Name | | TypologyGroup | utg | Name | | ClientId | cli | Oid | | Client | cli | Name | | ClientHasImage | cli | HasImage | | Product | pro | Name | | ProjectId | prj | Oid | | Project | prj | Name | | UserId | usl | Id | | User | usl | Name | | UserHasImage | usl | HasImage | | UserType | ust | Name | | FromMonth | — | datefromparts(...) | | ToMonth | — | datefromparts(...) | | Month | — | datefromparts(...) | | ContractedTime | — | (expression) | | PlannedContractedTime | — | (expression) | | PlannedTime | — | (expression) | | ActualTime | — | (expression) | | ContractedCost | — | (expression) | | PlannedCost | — | (expression) | | ActualCost | — | (expression) | | ContractedIncome | — | (expression) | | PlannedIncome | — | (expression) | | ActualIncome | — | (expression) | | ContractedProfit | — | (expression) | | PlannedProfit | — | (expression) | | ActualProfit | — | (expression) | | CompanyContractedCost | — | (expression) | | CompanyPlannedCost | — | (expression) | | CompanyActualCost | — | (expression) | | CompanyContractedIncome | — | (expression) | | CompanyPlannedIncome | — | (expression) | | CompanyActualIncome | — | (expression) | | CompanyContractedProfit | — | (expression) | | CompanyPlannedProfit | — | (expression) | | CompanyActualProfit | — | (expression) | | Exchange | — | (expression) | | CurrencySymbol | — | (expression) | | CurrencyCompany | prc | Name | | CurrencyCompanySymbol | ccr | Symbol | ## Source Tables | Table | Alias | Join | |-------|-------|------| | Company | com | FROM | | Division | div | FROM | | Department | dep | FROM | | UserTypologyGroup | utg | FROM | | Currency | cur | FROM | | Currency | ccr | FROM | | Project | prj | FROM | | Company | prc | FROM | | CommercialClient | cli | LEFT JOIN | | CommercialClientProduct | pro | LEFT JOIN | | UserLookUp | usl | LEFT JOIN | | UserType | ust | LEFT JOIN | *Version: 1 · Category: Scheduler · System: No* --- ## Execute API URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/execute-api Summary: This method can be used inside any workspace. #### Description This method can be used inside any workspace. To call the API service and execute a Restful operation. #### Method(s) ```javascript public executeAPI( method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH", relativePath: string, params?: { [name: string]: string }, body?: object, showToast = true, headers: { [name: string]: string } = {}, setContentTypeHeader = true, setProfileRequest = true, useCache = false ): Promise { return this.executeApiService.executeAPI( Apis.apiV2, method, relativePath, params, body, showToast, headers, setContentTypeHeader, setProfileRequest, useCache ); } ``` Parameter Type Required Defaults Description method String true Set the type of request relativePath String true Url request params String false Parameters that are intended to be passed in the request body String false The content to replace with showToast String false true To return a toast related to the request when error occurs headers String false empty Meta-data associated with the API request and response setContentTypeHeader String false true If it's set to true it will append 'Content-Type' to the header with the value 'application-json' setProfileRequest String false true If it's set to true it will append 'x-sw-profilerequest' to the header with the value 'true' useCache String false false If it's set to true it will cache the request #### Basic Usage ```javascript SW.executeAPI("GET", "documentBriefs", { documentId: "d8615b0f-4b52-4360-8f61-62c62bcb5463", }); ``` #### Example --- ## Export URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/utils/utils-export Summary: A sub namespace of Utils, exclusive for export operations --- # Export A sub namespace of Utils, exclusive for export operations --- ## toWorksheet #### Description This method can be used to export data into an excel sheet. #### Method(s) ```javascript 1 function toWorksheet(data: object[], fileName: string, sheetName: string = undefined) ``` Parameter Type Required Defaults Description data object[] true Data to export fileName string true Name for the exported file sheetName string false Name for the sheet #### Basic Usage ```javascript SW.Utils.Export.toWorksheet(['One', 'Two'], 'TestName', 'SheetTestName'); ``` #### Response This method will download a xlsx file named "TestName" with the data given in a sheet with the name "SheetTestName". --- ## toCsv #### Description This method can be used to export data into an excel sheet. #### Method(s) ```javascript 1 function toCsv(options: ExportOption, data: any): void ``` Parameter Type Required Defaults Description options ExportOption false Export options data any false Data to export #### Basic Usage ```javascript SW.Utils.Export.toCsv({filename: 'TestName'}, ['One', 'Two']) ``` #### Response This method will download a csv file named "TestName" with the data given. --- ## Export data to a CSV file and deliver it URL: https://documentation.skillsworkflow.com/docs/build-and-extend/automations/recipes/export-to-csv Summary: A common automation: fetch a set of records, turn them into a CSV file, and send that file to another system. A common automation: fetch a set of records, turn them into a CSV file, and send that file to another system. The chain looks like this — click any step for what it does: ## How it works 1. **[Start](../actions-reference.md#start)** hands off to the first action. 2. **[Rest](../actions-reference.md#rest)** (`GetData`) fetches the rows to export — here, from a named analytics query. 3. **[Csv](../actions-reference.md#csv)** (`CreateCsv`) turns those rows into a CSV, choosing which columns to include with `dataColumns`. 4. **[Rest](../actions-reference.md#rest)** (`DeliverFile`) sends the file on, attaching it as Base64 with the `ToBase64` pipe: `{{['CreateCsv']$ | ToBase64}}`. 5. **[Result](../actions-reference.md#result)** returns the outcome. ## The full automation ```json title="ExportExpensesToCsv" [ { "actionType": "Start", "name": "Start", "next": "GetData" }, { "actionType": "Rest", "name": "GetData", "next": "CreateCsv", "Method": "POST", "bodyMediaType": "Json", "url": "https://apiv2.example.com/api/analytics/globalQuery/Expense - Export/execute", "body": "{}" }, { "actionType": "CreateCsv", "name": "CreateCsv", "next": "DeliverFile", "hasHeaderRecord": true, "delimiter": ",", "quote": "\"", "data": "{{['GetData'].Content.Data}}", "dataColumns": [ "Employee", "CostCenter", "TotalValue", "ExpenseDate" ] }, { "actionType": "Rest", "name": "DeliverFile", "next": "Exit", "Method": "POST", "bodyMediaType": "Raw", "url": "https://intake.example.com/api/files", "body": "{\"fileName\":\"expenses.csv\",\"content\":\"{{['CreateCsv']$ | ToBase64}}\"}", "requestHeaders": [ { "name": "Content-Type", "value": "application/json" } ] }, { "actionType": "Result", "name": "Exit", "httpResponse": { "statusCode": 200, "headers": {}, "body": "{{['DeliverFile']}}" } } ] ``` Change the query URL and `dataColumns` to your data, and point `DeliverFile` at wherever the file should go. To email the file instead, swap `DeliverFile` for an [E-mail](../actions-reference.md#e-mail) action — see [Send an email notification](./email-notification.md). --- ## Expressions URL: https://documentation.skillsworkflow.com/docs/build-and-extend/automations/expressions Summary: How actions in an Automation Workflow read each other's results: the double-brace syntax, action content, the request that triggered the run, parameters, and the #eval preprocessor. Actions do not receive arguments from each other directly. Each one writes its result into the run's context under its own name, and later actions read from that context with an expression. An expression is written between double braces: ``` {{['ActionName']}} ``` ## Reading an action's result Every action produces a result, available under the action's `name`. Add a [JSONPath](./jsonpath.md) expression to reach inside it. ```json title="Using the Uri from an earlier GetProjectFile action" { "actionType": "Download", "name": "DownloadFile", "next": "UploadFile", "url": "{{['GetProjectFile']$.Content.Uri}}" } ``` `$` is the root of the referenced result. `.Content` is where most actions put what they produced, so `{{['ActionName']$.Content}}` is the shape you will write most often. ## Reading the triggering request `{{['#HttpRequest']}}` holds the request that started the run: scheme, host, path, method, query, headers and body. It is the one context entry that is not an action. ``` {{['#HttpRequest'].Body.Name}} {{['#HttpRequest'].Query.TenantName}} ``` Scheduled runs have no inbound request, so there is nothing useful in it. See [How automations start](../triggers.md). ## Reading parameters [`SetParameter`](../actions-reference.md#setparameter) stores a value under a name you choose, and it is read back exactly like an action result: ``` {{['SupplierCode']}} ``` Use it to compute something once and quote it in several later actions, rather than repeating the same long expression. ## Preprocessors `#eval()` evaluates its argument first and substitutes the value, which lets you build an expression whose *shape* depends on data. It can appear anywhere in an expression, including inside a JSONPath filter. ```json title="Examples" { "example1": "{{['#eval(['MapCustomDatabaseForm'].Name)'].Content}}", "example2": "{{['RecordsList'].Content..#eval(['MapCustomDatabaseForm'].Id)}}", "example3": "{{['RecordsList'].Content..#eval(['MapCustomDatabaseForm'].name).#eval(['MapCustomDatabaseForm'].Id)}}" } ``` Reach for it only when a plain expression cannot express what you need. Nested preprocessors are hard to read and harder to debug. ## Related articles - [Functions and pipe functions](./functions.md) - [JSONPath](./jsonpath.md) - [Actions](../actions-reference.md) --- ## File System URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/filesystem Summary: The namespace FileSystem provides to developers a method to easily upload files to a folder. # File System The namespace FileSystem provides to developers a method to easily upload files to a folder. ```javascript //accessing to FileSystem methods SW.FileSystem.{methodName} ``` --- ## uploadFilesToFolder #### Description This method can be used to upload files to a folder. #### Method(s) ```javascript 1 declare function uploadFilesToFolder(folderId: string, files: any[], documentId: string = null, documentType: string = null) : Promise; ``` Parameter Type Required Defaults Description folderId string true Folder id files any[] true Files to upload documentId string false null Document id documentType string false null Document type #### Basic Usage ```javascript SW.FileSystem.uploadFilesToFolder('folderId', [example.xlsx, example.png]); ``` --- ## Functions and pipe functions URL: https://documentation.skillsworkflow.com/docs/build-and-extend/automations/expressions/functions Summary: The functions that generate a value inside an Automation Workflow expression, and the pipe functions that transform one — converters, string, arithmetic, date and boolean operators. Two things can appear inside an expression besides a lookup. A **function** produces a value out of nothing. A **pipe function** transforms a value you already have. ## Functions Written on their own, with no value in front of them. | Function | Returns | |---|---| | `{{NewGuid}}` | A new GUID. | | `{{EmptyGuid}}` | The empty GUID, `00000000-0000-0000-0000-000000000000`. | | `{{NewDateUtc(value)}}` | A UTC date and time. The argument is required. | `NewDateUtc` accepts: | Argument | Returns | |---|---| | `Now` | The current UTC date and time. | | `Today` | Today at midnight. | | `Yesterday` | Yesterday at midnight. | | `FirstDayOfYear` | 1 January of the current year, at midnight. | | `LastDayOfYear` | 31 December of the current year, at midnight. | ``` {{NewDateUtc(Now)}} {{NewDateUtc(FirstDayOfYear)}} ``` ## Pipe functions A pipe function goes after a value, separated by `|`. Some take an argument in parentheses. They chain, left to right. ``` {{['GetProjectFile']$.Content.Url | UrlEncode}} {{['StartDate'] | AddDays(-1) | ToDateUtc}} ``` ### Converters | Pipe | Effect | |---|---| | `ToBase64` | Encodes the value as Base64. | | `FromBase64` | Decodes a Base64 value. | | `UrlEncode` | Escapes the value for use in a URL. | | `ToJson` | Parses the value into JSON. | | `ToJsonString` | Serialises the value to a JSON string. | | `ToDateUtc` | Reads the value as a UTC date and time. | | `FromUnixTimeSeconds` | Converts a Unix timestamp in seconds to a date. | | `FromUnixTimeMilliSeconds` | Converts a Unix timestamp in milliseconds to a date. | ``` {{['CreateCsv']$ | ToBase64}} {{['GetProjectFile']$.Content | ToJsonString}} ``` ### Strings | Pipe | Effect | |---|---| | `Trim` | Removes surrounding whitespace. | | `ToLowerCase` | Lowercases the value. | | `ToUpperCase` | Uppercases the value. | | `ToLowerCamelCase` | Converts the value to lowerCamelCase. | | `ToUpperCamelCase` | Converts the value to UpperCamelCase. | | `RemoveLeading('value')` | Removes `value` from the start. | | `RemoveTrailing('value')` | Removes `value` from the end. | | `Join('value')` | Appends `value`, or joins an array with it as separator. | | `Split('value')` | Splits on `value`. | ``` {{['MyText'] | RemoveLeading('DRAFT-') | Trim}} {{['Codes']$ | Join(',')}} ``` ### Tests | Pipe | Effect | |---|---| | `IsNullOrEmpty` | True when the value is null or empty. | | `Contains('value')` | True when the value contains `value`. | These are what a [`Case`](../actions-reference.md#case) action's `test` is usually built from. ### Arithmetic | Pipe | Effect | |---|---| | `AddDecimal(value)` | Adds `value` to a number. | | `Sum` | Sums an array. | | `Min` | Smallest value in an array. | | `Max` | Largest value in an array. | | `Avg` | Mean of an array. | ``` {{['ArrayOfValues']$ | Sum}} ``` ### Dates | Pipe | Effect | |---|---| | `AddMonths(value)` | Shifts a date by whole months. | | `AddDays(value)` | Shifts a date by whole days. | | `AddHours(value)` | Shifts a date by hours. | | `AddMinutes(value)` | Shifts a date by minutes. | Negative arguments move backwards. ``` {{NewDateUtc(Today) | AddDays(-1)}} ``` ## Related articles - [Writing expressions](./index.md) - [JSONPath](./jsonpath.md) --- ## Grid URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/ui/ui-grid Summary: A sub namespace of UI, exclusive for grid operations --- # Grid A sub namespace of UI, exclusive for grid operations ```javascript //accessing to ui.grid methods SW.UI.Grid.{methodName} ``` --- ## addToolbarButtons #### Description This method can be to add buttons in the grid toolbar. #### Method(s) ```js {3} 1 function addToolbarButtons(toolbarEvent: any, buttonsList: Button[]): void; ``` Parameter Type Required Defaults Description toolbarEvent any true The target dataGrid buttonsList Button true Buttons to add #### Basic Usage ```javascript SW.UI.Grid.addToolbarButtons(toolbarEvent, buttonsList); ``` --- ## calculatePercentageSummary #### Description This method can be used to calculate summaries with percentages. #### Method(s) ```js {3} 1 function calculatePercentageSummary(options: any, dividend: number[], divisor: number[]): void ``` Parameter Type Required Defaults Description options any true Summary options dividend number[] true Array of dividends divisor number[] true Array of divisors #### Basic Usage ```javascript SW.UI.Grid.calculatePercentageSummary(options, [1,2,3], [4,5,6]); ``` #### Response --- ## delete #### Description This method can be used to delete grid rows. #### Method(s) ```js {3} 1 function delete(documentName: string, dataGrid: dxDataGrid, params: { idField?: string } = {}): void ``` Parameter Type Required Defaults Description documentName string true Document name dataGrid dxDataGrid true Target datagrid idField string false Field to delete #### Basic Usage ```javascript SW.UI.Grid.delete("company", dataGrid); ``` --- ## expandCollapseRows #### Description This method can be used inside any workspace. To expand or collapse specified Grid rows. #### Method(s) ```javascript 1 function expandCollapseRows(dataGrid: dxDataGrid, 2 params: { 3 expandPriority?: boolean 4 } = { 5 expandPriority: true 6 } 7 ): void ``` Parameter Type Required Defaults Description dataGrid dxDataGrid true Target datagrid expandPriority boolean false true Flag to set if the rows are to expanded or collapsed instead #### Basic Usage ```javascript SW.UI.grid.expandCollapseRow(dataGrid.component); ``` #### Response --- ## exportToPdf #### Description This method allows the grid to be exported as PDF. #### Method(s) ```js 1 public exportToPdf( dataGrid: dxDataGrid, fileName: string, pdfDataGridOptions: PdfExportDataGridProps = {}, pdfOptions?: jsPDFOptions ); ``` Parameter Type Required Defaults Description dataGrid dxDataGrid true Target datagrid fileName string true Chosen file name pdfDataGridOptions PdfExportDataGridProps true PDF Grid related options pdfOptions jsPDFOptions false PDF exporting options #### PdfExportDataGridProps Parameter Type Required Defaults Description autoTableOptions object false Options of the generated PDF table. Refer to the jsPDF-autoTable plugin documentation to see the full list of available customizations. selectedRowsOnly boolean false Specifies whether or not to export only selected rows. keepColumnWidths boolean false Specifies whether columns in the PDF file should have the same width as their source UI component's columns. #### jsPDFOptions Parameter Type Required Defaults Description orientation string false "p" | "portrait" | "l" | "landscape" Defines the orientation of the grid. #### Basic Usage ```javascript SW.UI.Grid.exportToPdf( workspaceContext.get("dataGrid"), "Timesheet Report", { keepColumnWidths: true, autoTableOptions: { styles: { fontSize: 8 } } }, { orientation: "landscape" }); ``` #### Example --- ## importExcel #### Description This method can be used to import a xlsx file into a datagrid. #### Method(s) ```js {3} 1 function importExcel(fileUpload: any, grid: dxDataGrid): void; ``` Parameter Type Required Defaults Description fileUpload any true File to be uploaded dataGrid dxDataGrid true Target datagrid #### Basic Usage ```javascript SW.UI.grid.importExcel(file, grid); ``` --- ## Holiday URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/document/document-holiday Summary: A sub namespace of Document, exclusive for holiday operations --- A sub namespace of Document, exclusive for holiday operations --- ## get #### Description This method can be used to get holidays from a company between two dates. #### Method(s) ```javascript 1 declare function get(companyId?: string, startDate?: Date, endDate?: Date): Promise ``` Parameter Type Required Defaults Description companyId string true Company's id startDate Date false Range start date endDate Date false Range end date #### Basic Usage ```javascript SW.Document.Holiday.get("bf54366c-4212-4099-b959-7c969b6c878f"); ``` --- ## How automations start URL: https://documentation.skillsworkflow.com/docs/build-and-extend/automations/triggers Summary: The three ways an Automation Workflow is started: a Skills Workflow event, an inbound webhook, or a schedule — and what each one makes available to the actions. An Automation Workflow does not run on its own. Something has to start it, and what starts it decides what the first action has to work with. ## System events A workflow can be attached to an event raised by Skills Workflow, such as a document being created or moving stage. The event's payload arrives as the request body and is read through `{{['#HttpRequest'].Body}}`. Use this when the automation is a business rule: notify a channel when a project is created, push a deliverable to an external system when it reaches a stage. ## Webhooks A [webhook](../api/webhooks.md) can name an Automation Workflow as its destination. The external system calls the webhook, and the workflow receives the whole request, not just the body. ```json title="What {{['#HttpRequest']}} carries" { "Scheme": "https", "Host": "integrationworkflow-skills-dev-we.azurewebsites.net", "Path": "/api/tenants/{tenantId}/integration-workflows/{AutomationId}/execute", "Method": "POST", "Query": { "TenantName": ["playground-dev"] }, "Headers": { "Accept": ["application/json"] }, "Body": { "parameter": "value" } } ``` Every part of that is reachable: `{{['#HttpRequest'].Method}}`, `{{['#HttpRequest'].Query.TenantName}}`, `{{['#HttpRequest'].Headers.Accept}}`, and so on. Because the caller waits for an answer, webhook-triggered workflows usually end in a `Result` action that returns a real status code and body. See [Result](./actions-reference.md#result). ### Requiring authentication `requiresAuthentication` on the workflow controls whether the inbound call must be authenticated. Leave it on for any endpoint reachable from outside. ## Schedules A workflow can carry a `scheduler` block and run on a cadence, with no event and no caller. This is how recurring syncs are built. | Field | Meaning | |---|---| | `unit` | How many periods between runs. Must be greater than zero. | | `periodicity` | `Minutes`, `Hours`, `Days`, `Weeks` or `Months`. | | `startDateUtc` | When the schedule begins. Cannot be left at its default. | | `userId` | The user the run executes as. Cannot be an empty GUID. | | `isActive` | Whether the schedule is currently running. | | `notification` | Optional notification settings for the run. | ```json title="A workflow that runs every six hours" { "name": "SyncSuppliersNightly", "active": true, "logLevelType": "Info", "requiresAuthentication": false, "scheduler": { "unit": 6, "periodicity": "Hours", "startDateUtc": "2026-01-05T02:00:00Z", "userId": "0f3b9c21-6d0e-4a55-9d6c-0b1f8b7d2a44", "isActive": true }, "actions": [] } ``` A scheduled run has no inbound request, so `{{['#HttpRequest']}}` holds nothing useful. Fetch what you need in the first actions instead, and use [`SetParameter`](./actions-reference.md#setparameter) to hold values the later chain depends on. Scheduling an automation ## Related articles - [Workflow structure](./workflow-structure.md) - [Actions](./actions-reference.md) - [Webhooks](../api/webhooks.md) --- ## Icons URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/ui/ui-icons Summary: A sub namespace of UI, exclusive for getting icons and files icon classes --- # Icons A sub namespace of UI, exclusive for getting icons and files icon classes --- ## Icons #### Description This property can be to used to get icons classes. #### Method ```js SW.UI.Icons; ``` #### Basic Usage ```javascript > SW.UI.Icons.job; 'fal fa-tasks' > SW.UI.Icons.project; 'fal fa-clipboard-list'; > SW.UI.Icons.contract; 'fal fa-briefcase'; ``` --- ## Files #### Description This property can be to used to get files icon classes. #### Method ```js SW.UI.Icons.Files; ``` #### Basic Usage ```javascript > SW.UI.Icons.Files.excel 'fal fa-file-excel' > SW.UI.Icons.Files.pdf 'fal fa-file-pdf' > SW.UI.Icons.Files.text 'fal fa-file-alt' ``` --- --- ## Integration API URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/integration-api Summary: The Integration API allows you to integrate documents and entities in Skills Workflow from external systems by linking them via an External ID. ## Overview The Integration API allows you to integrate documents and entities in Skills Workflow from external systems by linking them via an External ID. It is not intended for data extraction—use it to push or synchronize data (e.g. from financial systems, project-management tools, ERPs, attendance systems, etc.) into Skills Workflow. ### Purpose The Integration API is designed to enable seamless synchronization of data between Skills Workflow and external systems. It facilitates the creation, updating, and linking of entities in Skills Workflow with external applications through the use of unique External IDs. ### Use Cases Integrate Skills Workflow with external systems such as: - Financial systems (e.g., QuickBooks, Xero) - Project management tools (e.g., Asana, Jira, Trello) - ERPs and CRMs - Attendance or time-tracking systems - Custom data synchronization or push solutions ### Key Limitations - External ID linkage required: Entities in Skills Workflow must be linked to external systems using an External ID. - Not for data extraction: Use the Data Extraction API for querying or extracting data. - No direct reporting or analysis: This API is for synchronization and data pushing, not for reporting purposes. - Rate limits may apply: High-frequency synchronization should be managed to avoid hitting API rate limits. - Data consistency: Ensure the external systems are correctly mapped to prevent data mismatches during synchronization. If you need to _read_ or _query_ Skills Workflow data, or replicate parts of its behavior inside your own application, please use the **Client API** instead. ## Getting Started ### Authentication Before calling any endpoint, you must obtain the following credentials from our Support team: - **App Key** (`X-AppId`) - **App Secret** (`X-AppSecret`) - **Tenant ID** (`X-AppTenant`) > These are provided by the support team upon request. Include them in each request via HTTP headers: ```http X-AppTenant: X-AppId: X-AppSecret: X-AppUser: # Optional, if user-scoped filtering is required Content-Type: application/json ``` ### Environments Your subscription plan determines which environments are available: | Environment | Hostname | | ------------- | --------------------------------------------- | | Development | `integration-api-dev.skillsworkflow.com` | | Test | `integration-api-test.skillsworkflow.com` | | UAT | `integration-api-uat.skillsworkflow.com` | | Production | `integration-api.skillsworkflow.com` | Use the appropriate `{{Environment}}` variable in your URLs. ### Postman Collection To facilitate testing of the available queries, we provide a Postman collection file with all endpoints configured. You can download it from the link below: [Download Postman Collection - Integration API](/templates/integration-api-postman-collention.json) After downloading, make sure to configure the variables `{{Environment}}`, `{{TenantId}}`, `{{AppId}}`, `{{AppSecret}}`, and `{{UserId}}` according to the credentials you have been given. ### Rate Limits All calls to the Integration API are capped at **30 seconds** execution time. To avoid timeouts: - Use **filters** on query endpoints - Implement **pagination** via `skip` and `take` query parameters --- ## Endpoints ### Users #### Create or Update a User - **Method**: `POST` - **URL**: ``` https://integration-api-{{Environment}}.skillsworkflow.com/api/users ``` - **Headers**: see _Common Request Headers_ - **Body Parameters**: | Parameter | Type | Required | Description | | --------------------------- | --------- | -------- | -------------------------------------------------------- | | `Id` | Guid | No | Not required; server will generate if omitted | | `UserName` | string | Yes | Login name | | `Name` | string | No | Full name | | `ExternalId` | string | Yes | Unique external identifier | | `EmployeeId` | Guid | No | Corresponding employee record ID in Skills Workflow | | `CompanyCode` | string | Yes | Company code used in Skills Workflow | | `DepartmentExternalId` | string | Yes | External ID of the department | | `TypologyExternalId` | string | Yes | External ID of the user typology | | `Mail` | string | No | Email address | | `IsActive` | bool | Yes | `true` = active, `false` = inactive | | `HireDate` | DateTime | No | ISO-8601 date of hire | | `SsoUserName` | string | No | SSO username | | `ExpirationDate` | DateTime | No | ISO-8601 account expiration date | | `RequiredWeeklyHours` | double | No | Weekly required hours | | `RequiredHours` | double | No | Daily required hours | | `LeaveDayHours` | double | No | Leave-day hours | | `ResponsibleId` | Guid | No | ID of the responsible user | | `UserTypeId` | Guid | No | User-type identifier | | `WeeklyOvertimeThresholdHours` | double | No | Weekly overtime threshold | | `Phone` | string | No | Telephone number | | `SsoOnly` | bool | No | `true` = SSO-only login | | `AdUserName` | string | No | Active Directory username | | `Tolerance` | int | No | Tolerance in minutes | | `ChangePasswordOnFirstLogon`| bool | No | Force password change on first login | | `TaxPayerNumber` | string | No | Taxpayer identification number | | `StartDate` | DateTime | No | ISO-8601 user start date | #### Partially Update a User - **Method**: `PATCH` - **URL**: ``` https://integration-api-{{Environment}}.skillsworkflow.com/api/users/{id} ``` - **Headers**: see _Common Request Headers_ - **Body**: only include the fields you want to update, each wrapped in a `{ "value": ... }` object. Do _not_ send fields you’re not changing. | Field | Type | Description | | ------------------------------------- | --------- | ------------------------------------------------ | | `Password.value` | string | New password (omit if not changing) | | `EntryTimeTotalMinutes.value` | int | Daily entry time in minutes | | `ExitTimeTotalMinutes.value` | int | Daily exit time in minutes | | `EntryTimeToleranceTotalMinutes.value`| int | Entry tolerance minutes | | `ExitTimeToleranceTotalMinutes.value` | int | Exit tolerance minutes | | `OffsetTotalMinutes.value` | int | Time offset | | `PaidUndertime.value` | bool | Pay undertime | | `PaidOvertime.value` | bool | Pay overtime | | `StartDate.value` | DateTime | New start date | | `ExpirationDate.value` | DateTime | New expiration date | | `UserName.value` | string | New login name | | `Name.value` | string | New full name | | `ExternalId.value` | string | New external ID | | `CompanyId.value` | Guid | New company ID | | `EmployeeId.value` | Guid | New employee ID | | `DepartmentId.value` | Guid | New department ID | | `TypologyId.value` | Guid | New typology ID | | `IsActive.value` | bool | Activate/deactivate | | `HireDate.value` | DateTime | New hire date | | `SsoUserName.value` | string | New SSO username | | `RequiredHours.value` | double | New required daily hours | | `LeaveDayHours.value` | double | New leave-day hours | | `RequiredWeeklyHours.value` | double | New required weekly hours | | `ResponsibleId.value` | Guid | New responsible user ID | | `UserTypeId.value` | Guid | New user-type ID | | `WeeklyOvertimeThresholdHours.value` | double | New weekly overtime threshold | | `ExternalNumber.value` | string | New external number | | `Phone.value` | string | New phone number | | `CityId.value` | Guid | New city ID | | `SsoOnly.value` | bool | Toggle SSO-only | | `AdUserName.value` | string | New AD username | | `Tolerance.value` | int | New tolerance | | `ChangePasswordOnFirstLogon.value` | bool | Toggle first-logon password change | | `TaxPayerNumber.value` | string | New taxpayer number | --- ### Employees #### Create or Update an Employee - **Method**: `POST` - **URL**: ``` https://integration-api-{{Environment}}.skillsworkflow.com/api/employees ``` - **Headers**: see _Common Request Headers_ - **Body Parameters**: | Parameter | Type | Required | Description | | ------------- | ------- | -------- | --------------------------------------- | | `Id` | Guid | No | Not required; server will generate if omitted | | `Name` | string | Yes | Employee’s full name | | `ExternalId` | string | Yes | Unique external identifier | | `CompanyId` | Guid | Yes | Company ID in Skills Workflow | | `IsActive` | bool | Yes | `true` = active, `false` = inactive | --- ## Example Usage Create a new user in the **Development** environment: ```bash curl -X POST "https://integration-api-dev.skillsworkflow.com/api/users" -H "X-AppTenant: " -H "X-AppId: " -H "X-AppSecret: " -H "Content-Type: application/json" -d '{ "UserName": "jdoe", "Name": "John Doe", "ExternalId": "EXT-USER-001", "CompanyCode": "COMPX", "DepartmentExternalId": "DEPT-100", "TypologyExternalId": "TYP-STD", "IsActive": true, "HireDate": "2025-04-29T00:00:00Z" }' ``` --- ## JSONPath URL: https://documentation.skillsworkflow.com/docs/build-and-extend/automations/expressions/jsonpath Summary: The JSONPath syntax used inside Automation Workflow expressions to reach into an action's result: operators, filters and a cheat sheet against a worked example. Once an expression names an action, JSONPath is how you reach into that action's result. `{{['GetClients']$.Content.documents.client[0].Name}}` is a lookup followed by a path. Paths accept dot notation, `$.store.book[0].title`, or bracket notation, `$['store']['book'][0]['title']`. Internal and output paths are always converted to bracket notation. ## Operators | Syntax | Description | |---|---| | `$` | The root object or element. | | `@` | The current object or element. | | `.` or `[ ]` | Child operator. | | `..` | Recursive descent. | | `*` | Wildcard. Every object or element, whatever its name. | | `[ ]` | Subscript operator, the native array operator in JSON. | | `[ , ]` | Union. Alternate names or array indices as a set. | | `[start : end : step]` | Array slice. | | `?()` | Applies a filter expression. | | `()` | Script expression, using the underlying script engine. | Filters use `?()` with `@` as the current object, as in `$.store.book[?(@.price < 10)].title`. Script expressions can stand in for an explicit name or index, as in `$.store.book[(@.length-1)].title`. ## A worked example Every expression in the cheat sheet below runs against this result: ```json { "documents": { "client": [ { "Id": "38ed55ac-cb45-4cbb-b89e-2f3cf480cb11", "Name": "Allbirds", "Code": "ABD", "HasContracts": false, "FullTimeEmployeeTime": 1800.0 }, { "Id": "3f826c2c-96c1-4d75-82d9-c29b4e50d4ef", "Name": "Amazon", "Code": "AMZ", "HasContracts": false, "FullTimeEmployeeTime": 0.0 }, { "Id": "682823e1-0651-4e8d-a655-ab3f8bcc8f6f", "Name": "Americanas", "Code": "", "HasContracts": false, "FullTimeEmployeeTime": 0.0 } ] } } ``` | Expression | Result | |---|---| | `$.documents.client[*].Name` | The names of every client. | | `$..Name` | Every name, at any depth. | | `$.documents.*` | Everything under `documents`. | | `$.documents..Code` | The code of everything under `documents`. | | `$..client[2]` | The third client. | | `$..client[(@.length-1)]` or `$..client[-1:]` | The last client. | | `$..client[0,1]` or `$..client[:2]` | The first two clients. | | `$..client[?(@.Code)]` | Clients that have a code. | | `$..client[?(@.FullTimeEmployeeTime>1800)]` | Clients above 1800 full-time employee time. | | `$..client[?(@.Name=='Americanas')]` | Clients named Americanas. | | `$..client[?(@.Name=='Amazon' && @.Code=='AMZ')]` | Clients matching both conditions. | | `$..client[?(@.Name=='Amazon' \|\| @.Code=='AMZ')]` | Clients matching either condition. | | `$..*` | Every member of the structure. | ## Preprocessors inside a path `#eval()` works inside a JSONPath expression, which lets a filter compare against a computed value: ``` $..client[?(@.Code=='#eval(#eval(NewDateUtc(Today) | AddDays(-1)))')] ``` ## Related articles - [Writing expressions](./index.md) - [Functions and pipe functions](./functions.md) --- ## Mark as Saved URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/markAsSaved Summary: This method can be used to mark changes as saved, so when navigating, the prompt will not be shown saying that are changes that were not saved --- #### Description This method can be used to mark changes as saved, so when navigating, the prompt will not be shown saying that are changes that were not saved #### Method(s) ```javascript function markAsSaved(dashboardDefinitionId: string): void ``` Parameter Type Required Description dashboardDefinitionId String true dashboard definition Id #### Basic Usage ```javascript SW.markAsSaved(workspaceContext.definition.Id); ``` #### Response --- --- ## Navigate URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/application/application-navigate Summary: A sub namespace of Application, exclusive for navigate operations --- # Navigate A sub namespace of Application, exclusive for navigate operations ```javascript //accessing to Application.Navigate methods SW.Application.Navigate.{methodName} ``` --- ## toDocument #### Description This method can be used to navigate do the document's feed. #### Method(s) ```javascript 1 function toDocument(documentName: DocumentName, documentId: string): void ``` Parameter Type Required Defaults Description documentName DocumentName true Document type to navigate documentId string true Document's id #### Basic Usage ```javascript SW.Application.Navigate.toDocument(SW.DocumentName.Client, 'clientId'); ``` #### Response When called it will navigate to the client's feed with the document id passed. --- ## toNewTab #### Description This method can be used to open a page in a new tab. #### Method(s) ```javascript 1 function toNewTab(url: string, 2 params?: { 3 useSkillsBaseUrl: boolean 4 } = { 5 useSkillsBaseUrl: true 6 } 7 ): void; ``` Parameter Type Required Defaults Description url string true Url Link useSkillsBaseUrl boolean false true Use Skills base url #### Basic Usage ```javascript SW.Application.Navigate.toNewTab("url"); ``` #### Response It will open a new tab with the url passed. --- ## toWorkspace #### Description This method can be used to navigate to a workspace. #### Method(s) ```javascript 1 function toWorkspace(workspaceId: string, 2 params: { 3 documentName?: DocumentName; 4 documentId?: string 5 } = {} 6 ): void ``` Parameter Type Required Defaults Description workspaceId string true Workspace id to navigate url String false " " Url Link documentName DocumentName false If the workspace is inside a document documentId string false Document id if the workspace is inside a document #### Basic Usage ```javascript SW.Application.Navigate.toWorkspace('workspaceId', {documentName: SW.DocumentName.Job, documentId: 'jobId'}); ``` #### Response It will navigate to a workspace that is inside the job document passed. --- ## Notification URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/service/service-notification Summary: A sub namespace of Service, exclusive for notification operations --- A sub namespace of Service, exclusive for notification operations ```javascript //accessing to service.notification methods SW.Service.Notification.{methodName} ``` --- ## get #### Description This method can be used to get notifications (paginated). `getAll` remains available as an alias for backward compatibility. #### Method(s) ```js 1 function get(params: { 2 skip: number, 3 take: number, 4 filter: string, 5 includeRead: boolean 6 } = { 7 skip: 0, 8 take: 20, 9 filter: "", 10 includeRead: true 11 }): Promise ``` Parameter Type Required Defaults Description skip number false 0 Number of records to skip (pagination offset) take number false 20 Number of records to return (page size) filter string false "" Search text includeRead boolean false true Include already read notifications #### Basic Usage ```javascript SW.Service.Notification.get(); ``` --- ## getGroupedByDocument #### Description This method can be used to get notifications grouped by document. #### Method(s) ```js 1 function getGroupedByDocument(params: { 2 skip: number, 3 take: number 4 } = { 5 skip: 0, 6 take: 20 7 }): Promise ``` Parameter Type Required Defaults Description skip number false 0 Number of records to skip (pagination offset) take number false 20 Number of groups to return #### Basic Usage ```javascript SW.Service.Notification.getGroupedByDocument(); ``` --- ## getUnreadCounter #### Description This method can be used to get the number of unread notifications. #### Method(s) ```js 1 function getUnreadCounter(): Promise ``` #### Basic Usage ```javascript SW.Service.Notification.getUnreadCounter(); ``` --- ## markAsRead #### Description This method can be used to mark notifications as read until a given date. #### Method(s) ```js 1 function markAsRead(untilDate: Date): Promise ``` Parameter Type Required Defaults Description untilDate Date true Mark as read until this date #### Basic Usage ```javascript SW.Service.Notification.markAsRead(new Date()); ``` --- ## markAsReadByDocument #### Description This method can be used to mark notifications as read from a given document. #### Method(s) ```js 1 function markAsReadByDocument(objectId: string, objectType: string): Promise ``` Parameter Type Required Defaults Description objectId string true Document id objectType string true Document name #### Basic Usage ```javascript SW.Service.Notification.markAsReadByDocument('jobId', 'job'); ``` --- ## send #### Description This method can be used to send a new notification. #### Method(s) ```js 1 function send(text: string, documentTypeName: string, documentId: string, userIdsToNotify: string[]): Promise ``` Parameter Type Required Defaults Description text string true Notification text documentTypeName string true Document name documentId string true Document id userIdsToNotify string[] true Users to receive the notification #### Basic Usage ```javascript SW.Service.Notification.send('New notification text', 'Deliverable', 'jobId', ['userId', 'userId']); ``` --- ## sendToBrowser #### Description This method can be used to display a browser notification directly in the UI. #### Method(s) ```js 1 function sendToBrowser(browserNotification: Interface.BrowserNotification): void ``` Parameter Type Required Defaults Description browserNotification Interface.BrowserNotification true Browser-compatible notification payload #### Basic Usage ```javascript SW.Service.Notification.sendToBrowser({ title: 'Workflow Alert', message: 'Your proof is ready for review.' }); ``` --- ## Panel URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/application/application-panel Summary: This method can be used inside any workspace. ## refresh #### Description This method can be used inside any workspace. Refresh the panel #### Method(s) ```javascript 1 declare function refresh(senderId: string): void; ``` Parameter Type Required Defaults Description senderId String true Sender's id #### Basic Usage ```javascript SW.Application.Panel.refresh('BAF13A4B-B0EE-4F64-B9F7-0543778CE383'); ``` ## refreshDataSource #### Description This method can be used inside any workspace. Refresh the datasource #### Method(s) ```javascript 1 declare function refreshDataSource(filters: Array<{ name: string; value: string }>, 2 params: {senderId: string, refreshSelf: boolean, callBacks?: { afterRefresh: Function }}): void; ``` Parameter Type Required Defaults Description filters Array true Filters for refresh query action senderId String true Sender's id refreshSelf Boolean true Flag for self refresh afterRefresh Function false Callback function triggered after the refresh #### Basic Usage ```javascript SW.Application.Panel.refreshDataSource([filters], "98226093-09B6-4E12-B9C6-2AEED2963C31"); ``` --- ## Popup URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/application/application-popup Summary: A sub namespace of Application, exclusive for popup operations --- # Popup A sub namespace of Application, exclusive for popup operations ```javascript //accessing to application.popup methods SW.Application.Popup.{methodName} ``` --- ## show #### Description This method can be used to create a popup with the specified entity and data. #### Method(s) ```javascript 1 function show( 2 dashboardTabs: DashboardTab[], 3 params: { 4 documentName?: DocumentName; 5 data?: any; 6 container?: DOMComponent; 7 width?: number; 8 height?: number; 9 enableScroll?: boolean; 10 title?: string; 11 openInFullScreen?: boolean; 12 hideTabContainer?: boolean; 13 hideSubHeader?: boolean; 14 closeOnOutsideClick?: boolean; 15 onClose?: Function; 16 buttonsConfiguration?: DashboardButtonsConfiguration; 17 } = { 18 width: 800, 19 height: 500, 20 closeOnOutsideClick: true 21 } 22 ): void ``` Parameter Type Required Defaults Description dashboardTabs DashboardTab true An array of DashboardTabs documentName DocumentName false Document's name data any false Data to pass to the popup container DOMComponent false Container component width number false 800 It sets the pop-up's width (pixels) height number false 350 It sets the pop-up's height (pixels) enableScroll boolean false To enable scrolling in the pop-up title string false Pop-up's title openInFullScreen boolean false Pop-up open in full screen hideTabContainer boolean false To hide sub container hideSubHeader boolean false To hide sub header closeOnOutsideClick boolean false true Close pop by clicking outside the pop-up area onClose Function false Action/Behaviour to be implemented on closing the pop-up buttonsConfiguration DashboardButtonsConfiguration false Enable configuration buttons #### Basic Usage ```javascript SW.Application.Popup.show([{ Id: '63a12710-3dcd-4d99-85f4-1214d6a4d55e', Title: 'Info' }], { documentName: SW.DocumentName.Job, width: 500, height: 200, enableScroll: false, title: 'Job', openInFullScreen: false, hideTabContainer: false, hideSubHeader: true, closeOnOutsideClick: false } ); ``` #### Response It will open a popup with the passed configuration. --- ## showBulk #### Description This method can be used to generate a pop-up to allow editing in bulk. #### Method(s) ```js {3} 1 function showBulk(documentName: DocumentName, dataGrid: dxDataGrid, 2 params: { 3 width?: number; 4 height?: number; 5 } = { 6 width: 800, 7 height: 500 8 } 9 ): void ``` Parameter Type Required Defaults Description documentName DocumentName true Document's name dataGrid dxDataGrid true DataGrid component width number false 800 It sets the new pop-up's width (pixels) height number false 500 It sets the new pop-up's height (pixels) #### Basic Usage ```javascript SW.Application.Popup.showBulk(SW.DocumentName.Employee, dataGrid); ``` #### Response --- ## showCreate #### Description This method can be used to add an add button on top, which calls a creation pop-up styled by the entity passed as parameter. #### Method(s) ```javascript 1 function showCreate(documentName: DocumentName, 2 params: { 3 width?: number; 4 height?: number; 5 container?: HTMLElement; 6 } = { 7 width: 800, 8 height: 350 9 } 10 ): void ``` Parameter Type Required Defaults Description documentName DocumentName true Document's name width number false 800 It sets the new pop-up's width (pixels) height number false 350 It sets the new pop-up's height (pixels) container HTMLElement false Container component #### Basic Usage ```javascript SW.Application.Popup.showCreate(SW.DocumentName.Company); ``` #### Response It will open a popup with the required field to create the document type passed. --- ## showConfirmation #### Description This method can be used to create a new popup with Yes and No buttons. If Yes button is pressed it will return true, else, it will return false. #### Method(s) ```javascript 1 function showConfirmation( 2 params: { 3 title?: string; 4 text?: string; 5 trueButtonText?: string; 6 falseButtonText?: string; 7 width?: number; 8 height?: number; 9 } = { 10 width: 400, 11 height: 150 12 } 13 ): Promise ``` Parameter Type Required Defaults Description title string false Popup title text string false Popup text trueButtonText string false True button text falseButtonText string false False button text width number false 400 It sets the new pop-up's width (pixels) height number false 150 It sets the new pop-up's height (pixels) #### Basic Usage ```javascript SW.Application.Popup.showConfirmation( params: { title: 'Popup title', text: 'Click one button', trueButtonText: 'Yes button', falseButtonText: 'No button', width: 400, height: 150 } ); ``` #### Response --- ## showPreview #### Description This method can be used to create a preview popup styled by the entity passed as parameter. #### Method(s) ```javascript 1 function showPreview(documentName: DocumentName, documentId: string, 2 params: { 3 dataGrid?: dxDataGrid; 4 fieldName?: string; 5 width?: number; 6 height?: number; 7 onSave?: Function; 8 onClose?: Function; 9 } = { 10 width: 800, 11 height: 500 12 } 13 ): void ``` Parameter Type Required Defaults Description documentName DocumentName true Document's name documentId string true Document's id dataGrid dxDataGrid false DataGrid component fieldName string false Field's name width number false 800 It sets the new pop-up's width (pixels) height number false 500 It sets the new pop-up's height (pixels) onSave function false Action/Behaviour to be implemented on saving the pop-up onClose function false Action/Behaviour to be implemented on closing the pop-up #### Basic Usage ```javascript SW.Application.Popup.showPreview(SW.DocumentName.Client, "ClientId"); ``` #### Response It will open a preview popup styled by the documentName passed as parameter. --- ## showPrompt #### Description This method can be used to create a new popup with Yes and No buttons and a textBox. If Yes button is pressed it will return the text written in the textBox, else, it will return null. #### Method(s) ```javascript 1 function showPromptPopup( params: { title?: string, text?: string, trueButtonText?: string, falseButtonText?: string, width?: number, height?: number } = { width: 400, height: 150 } ): Promise; ``` Parameter Type Required Defaults Description title string false Popup title text string false Popup text trueButtonText string false True button text falseButtonText string false False button text width number false 400 It sets the new pop-up's width (pixels) height number false 150 It sets the new pop-up's height (pixels) #### Basic Usage ```javascript SW.Application.Popup.showPromptPopup( params: { title: 'Popup title', text: 'Click one button', trueButtonText: 'Yes button', falseButtonText: 'No button', width: 400, height: 150 } ); ``` #### Response --- ## showSystemPreview #### Description This method can be used to open a preview popup styled by the documentName passed as parameter. #### Method(s) ```javascript 1 function showSystemPreview(documentName: DocumentName, documentId: string, 2 params: { 3 width?: number; 4 height?: number; 5 onClose?: Function; 6 } = { 7 width: 750, 8 height: 500 9 } 10 ): void ``` Parameter Type Required Defaults Description documentName DocumentName true Document's name documentId string true Document id width number false 750 It sets the new pop-up's width (pixels) height number false 500 It sets the new pop-up's height (pixels) onClose function false Action/Behaviour to be implemented on closing the pop-up when changes were made #### Basic Usage ```javascript SW.Application.Popup.showSystemPreview(SW.DocumentName.Estimate, 'estimateId'); ``` #### Response It will open a preview popup styled by the documentName passed as parameter. --- ## Realtime URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/realtime Summary: With this namespace, you can quickly provide methods to manipulate live updates. # Realtime With this namespace, you can quickly provide methods to manipulate live updates. The namespace Realtime provides to developers, methods to easily subscribe, unsubscribe, save subscriptions and get subscriptions from documents. ```javascript //accessing to Realtime methods SW.Realtime.{methodName} ``` --- ## getCurrentSubscriptions #### Description This method can be used to get the all current subscriptions. #### Method(s) ```javascript 1 declare function getCurrentSubscriptions(): {[key: string]: DocumentSubscription[]}; ``` #### Basic Usage ```javascript SW.Realtime.getCurrentSubscriptions(); ``` --- ## getDocumentComponentSubscription #### Description This method can be used to get a document subscription and the component. #### Method(s) ```javascript 1 declare function getDocumentComponentSubscription(documentType: string, documentId: string, component: any)): DocumentComponentSubscription; ``` Parameter Type Required Defaults Description documentType string true Document type documentId string true Document id component any true Component where was subscribed #### Basic Usage ```javascript SW.Realtime.getDocumentComponentSubscription('job', 'jobId', e.component); ``` --- ## saveDocumentComponentSubscription #### Description This method can be used to save a document subscription and the component. #### Method(s) ```javascript 1 declare function saveDocumentComponentSubscription(documentType: string, documentId: string, component: any, documentSubscription: DocumentSubscription)): void; ``` Parameter Type Required Defaults Description documentType string true Document type documentId string true Document id component any true Component where was subscribed documentSubscription DocumentSubscription true The document subscription #### Basic Usage ```javascript SW.Realtime.saveDocumentComponentSubscription('job', 'jobId', e.component, { documentInfo: { DocumentId: 'jobId', DocumentTypeName: 'job' }, eventsCallbacks: { onDocumentUpdated: () => {} }, component: e.component } ); ``` --- ## subscribeDocuments #### Description This method can be used to subscribe documents. #### Method(s) ```javascript 1 declare function subscribeDocuments(documents: DocumentInfoModel[], eventsCallbacks: EventsCallbacks, component: any): Promise; ``` Parameter Type Required Defaults Description documents DocumentInfoModel true Documents to subscribe eventsCallbacks EventsCallbacks true Callbacks after some events component any true Component where is subscribed #### Basic Usage ```javascript SW.Realtime.subscribeDocuments( [{ DocumentId: 'jobId', DocumentTypeName: 'job' }], { onDocumentUpdated: () => {} }, e.component ); ``` --- ## unsubscribeDocuments #### Description This method can be used to unsubscribe Documents. #### Method(s) ```javascript 1 declare function unsubscribeDocuments(documentSubscriptions: DocumentSubscription[]): Promise; ``` Parameter Type Required Defaults Description documentSubscriptions DocumentSubscription[] true Documents subscriptions #### Basic Usage ```javascript SW.Realtime.unsubscribeDocuments( [{ documentInfo: { DocumentId: 'jobId', DocumentTypeName: 'job' }, eventsCallbacks: { onDocumentUpdated: () => {} }, component: e.component }] ); ``` --- ## Roles URL: https://documentation.skillsworkflow.com/docs/build-and-extend/workspaces/roles Summary: On this page you will find how to add roles to your workspace. ### Description On this page you will find how to add roles to your workspace. You can add more than one role to your workspace. To have access to the this option, you need to click in the roles section. Example --- ## SDK URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk Summary: The Skills Workflow SDK provides a set of namespaces with utility functions accessible through the global SW object. The Skills Workflow SDK provides a set of namespaces with utility functions accessible through the global `SW` object. These functions allow secure and controlled interaction with the platform, supporting integrations, customizations and automations within Custom Scripts or Automation Workflows. --- ## General Structure All SDK functions are available under the `SW` object, following this pattern: ```javascript SW.{Namespace}.{Function} ``` Example: ```javascript var date = "Wed Aug 25 2021 16:23:26 GMT+0100 (Western European Summer Time)"; SW.Utils.Datetime.timeAgo(date); ``` --- ## Combined Example ```javascript const user = SW.User.getCurrentUser() const today = SW.Utils.formatDate(new Date(), "DD/MM/YYYY") SW.UI.Alert.info("Hello " + user.displayName +"! Today is " + today) ``` --- ## Additional Notes - All functions must be used within an authorized platform context. - The `SW` object is available only in approved environments such as Automation Workflows or Custom Scripts. - For full details on available API endpoints, refer to the official documentation. --- ## Select Box URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/ui/ui-selectBox Summary: A sub namespace of UI, exclusive for select box operations --- # Select Box A sub namespace of UI, exclusive for select box operations ```javascript //accessing to ui.selectBox methods SW.UI.SelectBox.{methodName} ``` --- ## getLookupByEndpoint #### Description This method can be used to get a SelectBox's datasource. #### Method(s) ```js {3} 1 function getLookupByEndpoint(options: any, endpoint: string): Promise; ``` Parameter Type Required Defaults Description options any true SearchValue, skip and take endpoint string true Endpoint to retrieve the data #### Basic Usage ```javascript SW.UI.selectBox.getLookupByEndpoint({searchValue: '', skip: 0, take: 20}, "departments/lookup"); ``` --- ## setListWidth #### Description This method can be used to set a SelectBox's list width according to the largest item passed in element's datasource. #### Method(s) ```js {3} 1 function setListWidth(selectBox: {component: dxSelectBox, element: HTMLElement}): void ``` Parameter Type Required Defaults Description component dxSelectBox true Target select box element HTMLElement true #### Basic Usage ```javascript SW.UI.selectBox.setListWidth(selectBox); ``` --- ## Send an email notification URL: https://documentation.skillsworkflow.com/docs/build-and-extend/automations/recipes/email-notification Summary: When something happens in Skills Workflow, let people know by email — optionally pulling in extra detail first. When something happens in Skills Workflow, let people know by email — optionally pulling in extra detail first. Click any step to see what it does: ## How it works 1. **[Start](../actions-reference.md#start)** hands off to the first action. 2. **[Rest](../actions-reference.md#rest)** (`GetDetails`) is optional — use it to fetch extra information to include in the message. Drop this step if the trigger already carries everything you need via `{{['#HttpRequest']}}`. 3. **[E-mail](../actions-reference.md#e-mail)** (`SendEmail`) sends the notification. The `body` supports HTML and can reference earlier results with `{{['ActionName']}}`. 4. **[Result](../actions-reference.md#result)** returns once the email is sent. ## The full automation ```json title="NotifyByEmail" [ { "actionType": "Start", "name": "Start", "next": "GetDetails" }, { "actionType": "Rest", "name": "GetDetails", "next": "SendEmail", "Method": "GET", "url": "https://apiv2.example.com/api/projects/{{['#HttpRequest'].Body.Id}}" }, { "actionType": "Email", "name": "SendEmail", "next": "Exit", "subject": "New project created", "body": "Project {{['GetDetails'].Content.Name}} was just created.", "fromDisplayName": "Notifications | Skills Workflow", "toAddress": "team@example.com" }, { "actionType": "Result", "name": "Exit", "httpResponse": { "statusCode": 200, "headers": {}, "body": "" } } ] ``` Set `toAddress`, `subject` and `body` to your case. To attach a file — for example a generated CSV — see [Export data to a CSV file](./export-to-csv.md) and add the file to the E-mail action's `attachments`. --- ## Service URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/service Summary: The SW. Service namespace provides grouped access to business-level services in the Skills Workflow SDK. The `SW.Service` namespace provides grouped access to **business-level services** in the Skills Workflow SDK. Each service is exposed as a sub-namespace under `SW.Service`, for example: ```ts SW.Service.Notification ``` ## Description `SW.Service` acts as a central point for service-oriented SDK functionality. It simplifies access to specific platform capabilities by grouping related service methods together. This namespace provides: - A unified entry point for all service APIs. - Simplified interaction with platform features. - A consistent structure for integrating new services. ## Structure ```ts SW.Service = { Notification: SW.Service.Notification // ... }; ``` Each sub-namespace contains its own set of methods and data types. ## Example Usage ```ts // Accessing the Notification Service await SW.Service.Notification.send( "New comment added", "Job", "JOB-12345", ["USR-0001", "USR-0002"] ); ``` ## Purpose The `SW.Service` namespace is designed to: - Group available SDK services in a single access point. - Simplify common service operations. - Provide a clear and consistent API surface for developers. > See each subpage under `SW.Service.{ServiceName}` for specific details and examples. --- ## Set Columns URL: https://documentation.skillsworkflow.com/docs/build-and-extend/workspaces/panels/grid-set-columns Summary: A function used to set grid's columns in a workspace. A function used to set grid's columns in a workspace. By default, a column is created for each field of a data source object, but in most cases, it is redundant. To specify a set of columns to be created in a grid, assign an array specifying these columns to the columns property. Each object in it configures a single column. If a column does not need to be customized, this array may include the name of the field that provides data for this column. Each grid column is represented in this array by an object containing column settings or by a data source field that this column is bound to. Column properties define the behavior and appearance of a grid column. ```javascript { entity: "client", format: { type: "image", mapping: { id: "ClientId", name: "ClientName", hasImage: "ClientHasImage" }, properties: { hideName: true, size: "small", forceImage: false } }, caption: "Client", dataType: "string", dataField: "ClientName", alignment: "center", width: 50, allowEditing: false } ``` ## entity Setting up the Entity property, the standard display will be used. If the cell display needs to be configured, the format property allows defining other default displays according to the selected type. According to the type to be presented in the column, image, link or text, some additional fields must be available in the data source. Accepted Values: 'client' | 'company' | 'stage' | 'user' | 'team' Basic Usage ```javascript { entity: "client"; } ``` Basic Usage ```javascript { entity: "company"; } ``` Basic Usage ```javascript { entity: "stage"; } ``` Basic Usage ```javascript { entity: "user"; } ``` Basic Usage ```javascript { entity: "team"; } ``` mapping If the data source does not mapping to the defaults fields name, it can be mapped by using the mapping property: ```javascript { caption: "Requesters", dataType: "string", dataField: "RequestersNames", visible: false, alignment: "center", width: 150, entity: "team", format: { mapping: { id: "RequestersIds", name: "RequestersNames", hasImage: "RequestersHasImage" } } } ``` Example Description Customize the text and the background of the type's label using the column's entity. By default the background color appears without color and the text appears in black. To choose the color for each entity, first you need to go to the maintenance and define the colors for the background and the text Accept entities: "jobtype" | "leavetype" # Basic Usage Column name Type Required Description StyleJson Json true Add the column StyleJson in the DataSource ```javascript {6} { dataField: "JobType", caption: "Job Type", entity: "jobtype", format: { style: "style" }, dataType: "string" } ``` Example To use the entity without the format, the dataSource expects the "name of the entity + style" as column name. --- ## format Formats the cell before it is displayed. There are some standard formats available. By specifing its type the corresponding format will be displayed. ### type Accepted Values: 'undefined' | 'image' | 'link' | 'document' | 'date' | 'currency' | 'read' | 'priority' | 'stage' To setup the Image type, it is necessary that data source includes the entity: - Id - Name - HasImage Basic Usage ```javacript { entity: "client", format: { type: "image" } } ``` properties Properties withing format property customize the behavior and appearance of a default display. ```javacript { entity: "client", format: { type: "image", properties: { hideName: true, size: "small" } } ``` hideName: To hide the client name from the column and keep only the client image, set this property as true. size: To define the size of the image. Accepted Values: 'small' | 'medium' | 'large' Example Basic Usage ```javacript { entity: "client", format: { type: "link" } } ``` Basic Usage The follow examples shows how to display the name and the image of the document together. - With entity defined. ```javacript { dataField: "Name", caption: "Title", format: { type: "document", properties: { hideName: false, size: "small" } } } ``` - Without entity defined. ```javacript { dataField: "Document", caption: "Title", format: { type: "document", properties: { hideName: false, size: "small" }, mapping: { documentName: "Document", title: "Name" } } } ``` properties documentName: The name defined in the dataField. title: Define the name that appears in the UI. Could be different of the name of the dataField. Example Basic Usage The follow example shows how to convert an UTC date into local. By default the date is converted from Utc into local in the format "DD/MMMM/YYYY HH:mm". ```javascript { dataField: "CreatedOnUtc", caption: "Created On", format: { type: "date" } } ``` properties The following examples shows how to customize de appearance of the default behavior. format: Customize the format of the date in the UI. ```javascript { dataField: "CreatedOnUtc", caption: "Created On", format: { type: "date", properties: { format: "DD/MMM/YYY" } } ``` Format Type Required Example "HH:mm" string false 12:06 "DD/MM/YYYY" string false 12/05/2022 "DD/MM/YYYY HH:mm" string false 12/05/2022 12:06 "DD/MMM/YYYY HH:mm" string false 12/May/2022 12:06 displayInUtc: Allows to display the date in UTC. ```javascript { dataField: "CreatedOnUtc", caption: "Created On", format: { type: "date", properties: { format: "DD/MMM/YYY", displayInUtC: true } } } ``` Example enableColoring If enabled, it sets the background color of a date according to the following conditions: Red, if the date has already expired; Orange, if the date is due in two or less days; Green, if the date is due in more than 2 days. ```javascript { dataField: "CreatedOnUtc", caption: "Created On", format: { type: "date", enableColoring: true } } ``` Example Basic Usage The follow examples shows how to display the currency symbol in a currency column. ```javascript { dataField: "Cost", caption: "Cost", format: { type: "currency", properties: { precision: 1 }, mapping: { code: "CurrencyCode" } } } ``` properties precision: To choose how many decimal places are shown. symbol: The data field name that has the currency symbols. Example The follow examples shows how to display the read/unread symbol in a boolean column. ```javascript { dataField: "AlreadyRead", caption: "Read", format: { type: "read" } } ``` The follow example shows how to display the priority type. ```javascript { dataField: "Priority", caption: "Priority", dataType: "number", format: { type: "priority" } } ``` The follow examples shows how to display the stage type. ```javascript { dataField: "Name", entity: "stage", format: { mapping: { color: "Color", name: "Name" } } } ``` properties stage A property to map the name of the stage. color A property to map the color of the stage. --- ## caption Specifies a caption for the column. ## dataType Casts column values to a specific data type Accepted Values: 'string' | 'number' | 'date' | 'boolean' | 'object' | 'datetime' ## dataField Binds the column to a field of the dataSource. ## alignment Aligns the content of the column Accepted Values: undefined | 'center' | 'left' | 'right' ## width Specifies the column's width in pixels or as a percentage. Ignored if it is less than minWidth. Type: Number | String The property supports the following types of values: - Number - The column's width in pixels. - String - A CSS-accepted column width measurement (for example, "55px", "80%" and "auto") except relative units such as em, ch, vh, etc. ## allowEditing A flag to allow column editing ## required Makes a column required to fill Type: Boolean ```javascript { dataField: "example", required: true } ``` ## showZeroes show or hide the zeroes values Type: Boolean ```javascript { dataField: "From0To60", visible: true, dataType: "number", alignment: "right", format: { type: "fixedPoint", precision: 2, }, showZeroes: false } ``` ## header Customize the column header's by default the background color is grey and the label has the the default style of the system. Type: object ```javascript { dataField: "People", alignment: "center", header: { color: "green", label: { color: "white", font: { size: "25px", family: "Times New Roman" } } } } ``` ### color Change the background color of the Header. Type: string Accepted Values: name of the color, HEX code, RGB code ### label Customize the label of the column. Type: object #### color Change the color of the text. Type: string Accepted Values: name of the color, HEX code, RGB code ### font Change the font's size and family. Type: string - size: the value must be in pixels - family: font's family name ## caretPosition When setting the property, it will set the cursor in a certain position. By representing the cursor with a | , please check the example below: - editorOptions: `{caretPosition: 0}` the cursor will be placed in the position 0 = |00:00 - editorOptions: `{caretPosition: 1}` the cursor will be placed in the position 1 = 0|0:00 ```javascript {... editorOptions: { caretPosition: 1 } } ``` --- ## Set Items URL: https://documentation.skillsworkflow.com/docs/build-and-extend/workspaces/panels/form-set-items Summary: A function used to save User, Document and other fields in the form. ## saveOptions A function used to save User, Document and other fields in the form. ```js { saveOptions: { type: "document", fieldName: "Agreed Date", }, dataField: "AgreedDateUtc", label: { text: "Internal Due Date" } editorOptions: { type: "datetime", displayFormat: "dd/MM/yyy HH:mm", disabled: false }, editorType: "dxDateBox" } ``` ### type Accepted Values: 'document' | 'userfield' | 'other' ```js { saveOptions: { type: "document"; } } ``` ```js { saveOptions: "document", dataField: "AgreedDateUtc", label: { text: "Internal Due Date" } editorOptions: { type: "datetime", displayFormat: "dd/MM/yyy HH:mm", disabled: false }, editorType: "dxDateBox" } ``` ```js { saveOptions: { type: "userfield"; } } ``` ```js { saveOptions: { type: "others"; } } ``` - If the type is set as 'others', no further parameter needs to be passed into the saveOptions. - If is specified as parameter instead of an object. The value passed will set the 'type'. ### fieldName To assign the name you want to save the field. ```js { saveOptions: { type: "userField", fieldName: "Priority", dataType: 6 }, dataField: "Priority" editorType: "dxSelectBox" } ``` If no value is passed, it will use the dataField value. ### dataType To pass the User Data Type Id, it takes a value of type number. Properties only valid if the type propertie is set to 'userfield' ```js { saveOptions: { type: "userField", dataType: 6 }, dataField: "Priority" editorType: "dxSelectBox" } ``` DataType Number Date 1 Integer 3 Varchar100 6 VarcharMax 7 UniqueIdentifier 9 ### isMultipleSelection A parameter of type boolean to allow multisection. Default value: false. ```js { saveOptions: { type: "userField", dataType: 6, isMultipleSelection: true }, dataField: "Priority" editorType: "dxSelectBox" } ``` ### lookupFieldName To set the userfield lookup field name. ```js { saveOptions: { type: "userField", dataType: 6, isMultipleSelection: true lookupfieldName: "lookupPriority" }, dataField: "Priority" editorType: "dxSelectBox" } ``` --- ## format A function used to set the item format. ```js { saveOptions: "document", dataField: "Priority", label: { text: "Priority" }, format: { type: "priority" } } ``` ### type Accepted Values: 'priority' ```js { format: { type: "priority"; } } ``` --- ## useCache This property allows to cache the data and must be used for fields that has the entity defined By default the value is false ```js { saveOptions: "document", dataField: "Client", entity: "commercialclient", label: { text: "Client" }, editorType: "dxSelectBox", useCache: true } ``` It will not work for the following entities: - stage - user --- ## lookup ```js { dataField: "CompanyId", label: { text: "CompanyId" }, editorType: "dxSelectBox", entity: "company", editorOptions: { name: "CompanyId" lookup:{ endpoint: { load: "v3/payment-conditions/lookup", byKey: "v3/payment-conditions" }, dataSource: "", name: "lookupTemplate", dependencyEditor: "DivisionId", filterEditors: ["DivsionId", "DepartmentId"], filters: [ { name: "DocumentTypeName", value: "Skill.Module.BusinessObjects.PriceTable" }, ] } } } ``` --- ## custom editorOptions ```js { dataField: "CompanyId", label: { text: "CompanyId" }, editorType: "dxSelectBox", editorOptions: { name: "CompanyId", ...SW.UI.SelectBox.getEditorOptions( "v3/company", { endpointByKey: "v3/company" onBeforeLoad: function(a){ } } ) } } ``` ### entity uses the default lookup of the entity ### name used to save the component (string) ### load the endpoint to use for the load of the selectBox (string or function) ### byKey the endpoint to use as key of the selectBox (if it is used as a string it will put "/" + key + "lookup") (string or function) ### dataSource under development ### name (inside the property lookup) the name of the lookup that is not default (string) ### dependencyEditor the name of the field that will unlock the current field. The field could be a dxSelectBox, dxNumberBox, dxDateBox (string) ### filterEditors the name of the field that will unlock the current field. The field could be a dxSelectBox, dxNumberBox, dxDateBox (string or array) ### filters name: the name of the filter (string) value: the value of the filter (boolean, string) --- ## State Storing URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/state-storing Summary: This documentation describes the StateStoring namespace and its methods for storing and retrieving application state. # State Storing This documentation describes the StateStoring namespace and its methods for storing and retrieving application state. The StateStoring namespace provides functionalities for managing application state using browser local storage. The namespace provides two main methods: - set(key: string, value: any, useWorkspaceId?: boolean): void - get(key: string, useWorkspaceId?: boolean): string | object | Array ```javascript //accessing to State Storing methods SW.StateStoring.{methodName} ``` --- ## set #### Description This method stores a key-value pair in local storage. #### Method(s) ```javascript declare function set(key: string, value: any, useWorkspaceId?: boolean) : void; ``` Parameter Type Required Description key string true The key used to store the data. value any Required The data to be stored. Can be a string, object, or array. useWorkspaceId boolean optional Defaults to true. If false, the current workspace ID will not be prepend in the key. ## get #### Description This method retrieves data from local storage based on the provided key. #### Method(s) ```javascript declare function get(key: string, useWorkspaceId?: boolean) : string | object | Array; ``` Parameter Type Required Description key string true The key used to store the data. useWorkspaceId boolean optional Defaults to true. If false, attempts to retrieve data without the workspace ID prepended to the key. ## Basic Usage The useWorkspaceId parameter helps isolate application data for different workspaces. You can set useWorkspaceId to false when you want to access data outside of a specific workspace context. ```javascript // Set a string value SW.StateStoring.set('userLanguage', 'en'); // Get the string value const userLanguage = SW.StateStoring.get('userLanguage'); console.log(userLanguage); // Output: 'en' // Set a boolean value SW.StateStoring.set('isDarkModeEnabled', true); // Get the boolean value const isDarkModeEnabled = SW.StateStoring.get('isDarkModeEnabled'); console.log(isDarkModeEnabled); // Output: true // Set an object value const userProfile = { name: 'Alice', email: 'alice@example.com', preferences: { theme: 'dark', notifications: true, }, }; SW.StateStoring.set('userProfile', userProfile); // Get the object value const retrievedUserProfile = SW.StateStoring.get('userProfile'); console.log(retrievedUserProfile); // Output: { name: 'Alice', email: 'alice@example.com', preferences: { theme: 'dark', notifications: true } } // Set an array value const favoriteColors = ['blue', 'red', 'green']; SW.StateStoring.set('favoriteColors', favoriteColors); // Get the array value const retrievedFavoriteColors = SW.StateStoring.get('favoriteColors'); console.log(retrievedFavoriteColors); // Output: ['blue', 'red', 'green'] // Set a value without workspace ID SW.StateStoring.set('currentProject', 'project1', false); // Get the value with workspace ID const currentProject = SW.StateStoring.get('currentProject', false); console.log(currentProject); // Output: 'project1' (assuming the current workspace ID is associated with 'project1') // Set a value as Department ID SW.StateStoring.set('DepartmentId', '917e716e-08a8-43fa-931b-a45e00301751', false); // Get the value for Department ID const storedDepartmentId = SW.StateStoring.get('DepartmentId', false); console.log(storedDepartmentId); // Output: '917e716e-08a8-43fa-931b-a45e00301751' ``` --- ## Storage URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/storage Summary: With this namespace, you can quickly provide methods to manipulate the storage. # Storage With this namespace, you can quickly provide methods to manipulate the storage. The namespace Storage provides to developers, methods to easily get and import workspaces. ```javascript //accessing to Storage methods SW.Storage.{methodName} ``` --- ## getWorkspaces #### Description This method can be used to get workspaces from a given url. #### Method(s) ```javascript 1 declare function getWorkspaces(url: string): Promise; ``` Parameter Type Required Defaults Description url string true Url to get workspqces #### Basic Usage ```javascript SW.Storage.getWorkspaces('workspacesURLExample'); ``` --- ## importWorkspaces #### Description This method can be used to import workspaces from a given urls array to a tenant. #### Method(s) ```javascript 1 declare function importWorkspaces(urls: string[]): Promise; ``` Parameter Type Required Defaults Description url string[] true Urls to get workspqces #### Basic Usage ```javascript SW.Storage.importWorkspaces(['workspacesURL1', 'workspacesURL2']); ``` --- ## Store URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/store Summary: With this namespace, you can quickly provide methods to manipulate the data store. # Store With this namespace, you can quickly provide methods to manipulate the data store. The namespace Store provides to developers, methods to easily batch, delete, filter, get, insert, load, refresh and update data from the store. ```javascript //accessing to Store methods SW.Store.{methodName} ``` --- ## batch #### Description This method can be used to insert, delete or update a data source in the store. #### Method(s) ```javascript 1 declare function batch(dataSourceName: string, data: IDashboardStoreBatchUpdate, senderId: any): Promise; ``` Parameter Type Required Defaults Description dataSourceName string true Data source name data IDashboardStoreBatchUpdate true Operation and data to be modified senderId any false Sender id #### Basic Usage ```javascript SW.Store.batch('dataSourceName', {insert: ['newRow']}); SW.Store.batch('dataSourceName', {update: [{ row:{id: 'rowId', value: 'rowValue'}, data: 'rowData'}]}); SW.Store.batch('dataSourceName', {delete: [{id: 'rowId', value: 'rowValue'}]}); ``` --- ## delete #### Description This method can be used to delete a row in a data source. #### Method(s) ```javascript 1 declare function delete(dataSourceName: string, rowId: IDashboardStoreRow, senderId): Promise; ``` Parameter Type Required Defaults Description dataSourceName string true Data source name rowId IDashboardStoreRow true Row to delete senderId any false Sender id #### Basic Usage ```javascript SW.Store.delete('dataSourceName', {id: 'rowId', value: 'rowValue'}); ``` --- ## filter #### Description This method can be used to filter a data source from the store. #### Method(s) ```javascript 1 declare function filter(filters: DashboardStoreFilters, senderId = ""): void; ``` Parameter Type Required Defaults Description filters DashboardStoreFilters true Filters to apply senderId any false Sender id #### Basic Usage ```javascript SW.Store.filter({'dataSourceName': [{id: 'rowsId' , value: 'rowsValue'}]}); ``` --- ## get #### Description This method can be used to get a row in a data source. #### Method(s) ```javascript 1 declare function get(dataSourceName: string, rowId: IDashboardStoreRow, dashboardDefinitionId: string): Promise; ``` Parameter Type Required Defaults Description dataSourceName string true Data source name rowId IDashboardStoreRow false Row to get dashboardDefinitionId string false Workspace id #### Basic Usage ```javascript SW.Store.get('dataSourceName', {id: 'rowId', value: 'rowValue'}); ``` --- ## insert #### Description This method can be used to insert a row in a data source. #### Method(s) ```javascript 1 declare function insert(dataSourceName: string, rowData: any, senderId): Promise; ``` Parameter Type Required Defaults Description dataSourceName string true Data source name rowData any true New row data senderId any false Sender id #### Basic Usage ```javascript SW.Store.insert('dataSourceName', {'rowData'}); ``` --- ## load #### Description This method can be used to load more than one data source. #### Method(s) ```javascript 1 declare function load(dataSourceNames?: string[], filters?: DashboardFilter[], senderId?: string): Promise; ``` Parameter Type Required Defaults Description dataSourceName string[] false Data sources name filters DashboardFilter[] false Filters to apply senderId string false Sender id #### Basic Usage ```javascript SW.Store.load(['dataSourceName'], [{Name: 'FilterName', Value: 'FilterValue'}]); ``` --- ## refresh #### Description This method can be used to refresh a row from a data source. #### Method(s) ```javascript 1 declare function refresh(dataSourceName: string, rowId: { id: string; value: any }, senderId, filters): Promise; ``` Parameter Type Required Defaults Description dataSourceName string true Data source name rowId IDashboardStoreRow true Row to refresh senderId any false Sender id filters DashboardFilter[] false Filters to be used in Data Source #### Basic Usage ```javascript SW.Store.refresh('dataSourceName', {id: 'rowId', value: 'rowValue'}, senderId, [{Name: 'FilterName', Value: 'FilterValue'}]); ``` --- ## update #### Description This method can be used to update a row from a data source. #### Method(s) ```javascript 1 declare function update(dataSourceName: string, rowId: { id: string; value: any }, rowData: any, senderId): Promise; ``` Parameter Type Required Defaults Description dataSourceName string true Data source name rowId IDashboardStoreRow true Row to update rowData any true Row's new data senderId any false Sender id #### Basic Usage ```javascript SW.Store.update('dataSourceName', {id: 'rowId', value: 'rowValue'}, {'newData'}); ``` --- ## Store URL: https://documentation.skillsworkflow.com/docs/build-and-extend/workspaces/panels/datasource-store Summary: On this page you will find how to create a workspace using the Store as DataSource. On this page you will find how to create a workspace using the Store as DataSource. Basic Usage Parameters Description query Data of the query componentDefinitionId Id of the component customOperators Use this parameter to select the data source WorkspaceContext Use this parameter to have access to the context of the workspace ## ```js ( query, creators, operators, componentDefinitionId, customOperators, workspaceContext ) => creators.of(query).pipe( customOperators.selectDataSource("expense"), operators.map((queryData) => { const data = queryData.Data; return { Data: [...data], Filters: query.Filters }; }) ); ``` Example --- ## TagBox URL: https://documentation.skillsworkflow.com/docs/build-and-extend/workspaces/panels/form-tagbox Summary: On this page you will find TagBoxs examples as well as how to setup a TagBox. On this page you will find TagBoxs examples as well as how to setup a TagBox. ## Multiple Selection ### Description This example shows how to configure a TagBox inside a Form that: - Uses Custom Fields - Multiple Selection custom field - Lookup data from Workspace Store (query) ### Example #### Item Definition ```js { editorType: "dxTagBox", dataField: "CMS", saveOptions: { type: "userfield", fieldName: "CMS", dataType: 7, isMultipleSelection: true }, label: { text: "CMS" }, editorOptions: { searchEnabled: false, dataSource: { load: function (loadOptions) { return SW.Store.get('DeliverableUserfields').then( r => r.find(usf => usf.ColumnName == 'CMS').LookupValues.split(';')) }, byKey: function (e) { if (e) { return e; } } } } } ``` #### Query defined in Workspace Store --- ## Tooltip URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/ui/ui-tooltip Summary: A sub namespace of UI, exclusive for tooltip operations --- # Tooltip A sub namespace of UI, exclusive for tooltip operations ```javascript //accessing to ui.tooltip methods SW.UI.Tooltip.{methodName} ``` --- ## set #### Description This method can be used to set a new tooltip to a html element. #### Method(s) ```js {3} 1 function set(reference: HTMLElement, data: object | string, 2 params: { 3 documentName?: DocumentName, 4 tooltipOptions?: PopperContentOptions 5 } = {} 6 ): void ``` Parameter Type Required Defaults Description reference HTMLElement true Element's reference data object | string true Data to be displayed documentName DocumentName false Document name tooltipOptions PopperContentOptions false Tooltip options #### Basic Usage ```javascript SW.UI.Tooltip.set(element, jobData, { documentName: SW.DocumentName.Job }); ``` --- ## show #### Description This method can be used to show a tooptip in a html element. (When used, to hide the tooltip use SW.UI.Tooltip.hide()) #### Method(s) ```js {3} 1 function show(reference: HTMLElement, data: object | string, 2 params: { 3 documentName?: DocumentName, 4 tooltipOptions?: PopperContentOptions 5 } = {} 6 ): void ``` Parameter Type Required Defaults Description reference HTMLElement true Element's reference data object | string true Data to be displayed documentName DocumentName false Document name tooltipOptions PopperContentOptions false Tooltip options #### Basic Usage ```javascript SW.UI.Tooltip.(element, jobData, { documentName: SW.DocumentName.Job }); ``` --- ## hide #### Description This method can be used to hide a tooltip. (Only used when using SW.UI.Tooltip.show()) #### Method(s) ```js {3} 1 function hide(reference: HTMLElement): void ``` Parameter Type Required Defaults Description reference HTMLElement true Element's reference #### Basic Usage ```javascript SW.UI.tooltip.hide(element); ``` --- ## Translation URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/application/application-translation Summary: This method can be used to get the translation of some words or sentences. ## get #### Description This method can be used to get the translation of some words or sentences. #### Method(s) ```javascript 1 declare function get(value: string): string; ``` Parameter Type Required Defaults Description value string true Word or sentence to translate #### Basic Usage ```javascript SW.Application.Translation.get('Hello'); ``` --- ## UI URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/ui Summary: With this namespace, you can quickly provide methods to show UI. # User Interface With this namespace, you can quickly provide methods to show UI. The namespace User Interface provides to developers, methods to easily show or validate data. ```javascript //accessing to ui methods SW.UI.{methodName} ``` --- ## editComponentsOptionInBulk #### Description This method can be used to edit an option in various components. #### Method(s) ```javascript 1 function editComponentsOptionInBulk(components: any[], option: string, value: any): void ``` Parameter Type Required Defaults Description components any[] true Components array to edit option option string true Option to edit value any true New option value #### Basic Usage ```javascript SW.UI.editComponentsOptionInBulk([dataGrid, chart], "dataSource", data); ``` #### Response It will set dataGrid and chart dataSources with the variable data passed. --- ## getEntityImage #### Description This method can be used to get entities image. #### Method(s) ```javascript 1 function getEntityImage(element: HTMLElement, documentName: string, 2 params?: { 3 size?: Size; hideName?: boolean; title?: string; 4 } = { 5 size: Size.SMALL, hideName: false, title: null 6 } 7 ): string; ``` Parameter Type Required Defaults Description element HTMLElement true HTML element documentName string true Type of document size Size false "small" Image's size to be displayed(small, medium, large) hideName boolean false false Show or hide the name of the field Title string false false The name displayed in the UI #### Basic Usage ```javascript SW.UI.getEntityImage(element, "job", { size: "large" }); ``` #### Response Returns the passed HTML element with the entity job image. --- ## setAttribute #### Description This method can be used to set element's attributes. #### Method(s) ```javascript 1 function setAttribute(element: HTMLElement, attribute: string, attributeValue: string, 2 params: { 3 text?: string; 4 createContainer?: boolean 5 } = { 6 createContainer: true 7 } 8 ): HTMLElement ``` Parameter Type Required Defaults Description element HTMLElement true HTML element attribute string true Attribute to update attributeValue string true Value to update attribute text string false Inner HTML createContainer boolean false Create a new div container #### Basic Usage ```javascript SW.UI.setAttribute(element, "style", "display: contents"); ``` #### Response It will add the attribute value to the given attribute. --- ## setConditionalColor #### Description This method can be used to set element's attributes. #### Method(s) ```javascript 1 function setConditionalColor(element: HTMLElement, value: string, conditions: boolean[], colors: string[], 2 params: { 3 createContainer?: boolean; 4 bold?: boolean; 5 italic?: boolean 6 } = { 7 createContainer: true 8 } 9 ): void ``` Parameter Type Required Defaults Description element HTMLElement true HTML element value string true Value to show conditions boolean[] true Conditions to check colors string[] true Colors for conditions createContainer boolean false true Create a new div container bold boolean false Bold font italic boolean false Italic font #### Basic Usage ```javascript SW.UI.setConditionalColor(element, 'Value', [1>0, 1=0, 1<0], ['Red', 'Green', 'Blue']); ``` #### Response It will add the value text to the element with the background color corresponding to the condition that is true. --- ## setRag #### Description This method allows you to set an element as Red, Ambar or Green according to its value. #### Method(s) ```javascript 1 function setRag(element: any, value: string, 2 red: boolean, 3 ambar: boolean, 4 green: boolean, 5 params: { createContainer?: boolean } = { createContainer: true } 6 ): string; ``` Parameter Type Required Defaults Description element HTMLElement true HTML element value string true Value to show red boolean true return the value with background color in red ambar boolean true return the value with the background color in ambar green boolean true return the value with the background color in green createContainer boolean false true Create a new div container #### Basic Usage ```javascript SW.setRAG(e, value, i.value > 15, i.value >= 5 && i.value < 15, i.value < 5); ``` #### Response It will add the value text to the element with the background color corresponding to the condition that is true. #### Example ```javascript {7} { dataField: "MarginPercentage", dataType: "number", alignment: "center", format: "percent", width: 120, cellTemplate: function(e, i) { SW.UI.setRag(e, i.text, i.value < 0.01, i.value >= 0.01 && i.value < 0.99, i.value >= 0.99); } }, ``` --- ## setVersionRag #### Description This method can be used to set rag considering two given versions. #### Method(s) ```javascript 1 function setVersionRag(element: HTMLElement, version1: number, version2: number, 2 params: { 3 createContainer?: boolean 4 } = { 5 createContainer: true 6 } 7 ): void ``` Parameter Type Required Defaults Description element HTMLElement true HTML element version1 number true Version number version2 number true Version number createContainer boolean false true Create a new div container #### Basic Usage ```javascript SW.UI.setVersionRag(element, 1, 2); ``` #### Response --- ## showComponent #### Description This method can be used to create a new component. #### Method(s) ```javascript 1 function showComponent(element: HTMLElement, type: string, properties: object): void; ``` Parameter Type Required Defaults Description element HTMLElement true HTML tag type string true Component's type properties object true Component's properties #### Basic Usage ```javascript SW.UI.showComponent(element, "List", properties); ``` #### Example In the following example you can find a template for an item that will present a List of items: ```javascript function itemTemplate(itemData, itemIndex, itemElement, workspaceContext) { var properties = { items: [ { id: 1, value: "Blue" }, { id: 2, value: "Red" }, ], }; SW.UI.showComponent(itemElement, "List", properties); } ``` --- ## showImage #### Description This method can be used to display an existing or default Image. #### Method(s) ```javascript 1 function showImage(element: HTMLElement, documentName: "user" | "client" | "company", name: string, 2 params: { 3 hasImage?: boolean; 4 size?: Size; 5 id?: string; 6 showName: boolean 7 } = { 8 hasImage: false, 9 size: Size.SMALL, 10 showName: false 11 } 12 ): HTMLElement ``` Parameter Type Required Defaults Description element HTMLElement true HTML element documentName string true Document type ("user", "client", "company") name string true Document name hasImage boolean false A flag to specify if target already has an image size Size false Image size id string false Document id showName boolean false Show document name #### Basic Usage ```javascript SW.UI.showImage(element, "company", "Skills Workflow", { hasImage: true, id: "companyId", }); ``` #### Response --- ## showImageEditor #### Description This method can be used to update a user, client or company image. #### Method(s) ```javascript 1 function showImageEditor(element: HTMLElement, documentName: "user" | "client" | "company", documentId: string, 2 params: { 3 endpoint?: string; 4 size?: Size; 5 width?: number; 6 height?: number; 7 imageStyle?: string; 8 } = { 9 size: Size.LARGE, 10 width: 100, 11 height: 100 12 } 13 ): HTMLElement ``` Parameter Type Required Defaults Description element HTMLElement true HTML element documentName string true Image from document user, client or company documentId string true Document id endpoint string false Image's endpoint size Size false large Image's size to be displayed(small, medium, large) width number false 100 Container width in pixels height number false 100 Container height in pixels imageStyle string false Setting height & width in string format #### Basic Usage ```javascript SW.UI.showImageEditor(element, "company", "companyId"); ``` #### Response It will add the document image with an event listener 'change' to change it. --- ## showPriority #### Description This method can be used to define an element priority. #### Method(s) ```javascript 1 function showPriority(element: HTMLElement, priorityValue: number): void; ``` Parameter Type Required Defaults Description element HTMLElement true HTML element priorityValue number false Define element's priority #### Basic Usage ```javascript SW.UI.showPrioruty(element, 1); ``` #### Response --- ## showStage #### Description This method can be used to display a stage. #### Method(s) ```javascript 1 function showStage(element: HTMLElement, name: string, color: string, 2 params: { 3 grouping?: boolean; 4 groupCount?: number 5 } = {} 6 ): void ``` Parameter Type Required Defaults Description element HTMLElement true HTML element name string false Stage name color string false Element's color grouping boolean false A flag to define if target is grouped groupCount number false Set the number of elements to group #### Basic Usage ```javascript SW.UI.showStage(element, "Test", "blue"); ``` #### Response --- ## showTags #### Description This method can be used to display tags. #### Method(s) ```javascript 1 function showTags(element: HTMLElement, tags: string = null): void; ``` Parameter Type Required Defaults Description element HTMLElement true HTML element tags string false Tags to show #### Basic Usage ```javascript SW.UI.showTags(element, "{Label: Skills, Color: #333}"); ``` #### Response --- ## showTeam #### Description This method can be used to display teams. #### Method(s) ```javascript 1 function showTeam( 2 element: HTMLElement, 3 data: any, 4 idsFieldName: string, 5 namesFieldName: string, 6 hasImageFieldName: string, 7 params: { 8 size?: Size 9 } = { 10 size: Size.SMALL 11 } 12 ): void ``` Parameter Type Required Defaults Description element HTMLElement true HTML element data any true A set of data idsFieldName string true Users identifier namesFieldName string true Users name hasImageFieldName string true Flag if executers have images size Size false small Image's size #### Basic Usage ```javascript SW.UI.showTeam(element, data, "UserIds", "UserNames", "UserHasImages", { size: "large", }); ``` #### Response This method will add the user images to the given element.. #### Example ```javascript {9} { dataField: "ExecutorNames", caption: "Assignee", dataType: "string", allowEditing: false, visible: true, cellTemplate: function cellTemplate(e, i) { if (i.data && i.data.ExecutorNames) { SW.UI.showTeam(e, i, 'ExecutorIds', 'ExecutorNames', 'ExecutorHasImages', { size: 'small' }) } } }, ``` --- ## showWorkload #### Description This method can be used to display assignments workload. #### Method(s) ```javascript 1 function showWorkload(element: string | HTMLElement, assignmentId: string): Promise ``` Parameter Type Required Defaults Description element string | HTMLElement true HTML element or string assignmentId string true Assignment id #### Basic Usage ```javascript SW.UI.showWorkload(element, "assignmentId"); ``` #### Response --- ## User URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/document/document-user Summary: A sub namespace of Document, exclusive for user operations --- Get Custom Fields Get Lookup Set Custom Fields Update --- A sub namespace of Document, exclusive for user operations --- The same methods that are presented in the Document Introduction but do not take the first param documentName, because you're already in a User document [Get Custom Fields](./#getcustomfields) [Get Lookup](./#getlookup) [Set Custom Fields](./#setcustomfields) [Update](./#update) --- ## getImages #### Description This method can be used to get users image url. #### Method(s) ```javascript 1 declare function getImages(ids: string[]): string[]; ``` Parameter Type Required Defaults Description ids string[] true Array of user ids #### Basic Usage ```javascript SW.Document.User.getImages(["f6671567-67b2-430c-bf04-dc7a41e99395"]); ``` --- ## Utils URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/utils Summary: With this namespace, you can quickly access methods that perform common operations. # Utils With this namespace, you can quickly access methods that perform common operations. The namespace Utils provides to developers, methods to easily implement regularly used operations. ```javascript //accessing to utils methods SW.Utils.{methodName} ``` --- ## convertToString #### Description This method can be used to convert different variable types to string. #### Method(s) ```javascript 1 function convertToString(valueToConvert: any): string ``` Parameter Type Required Defaults Description valueToConvert any false Variable to convert(boolean, number, function, array, object) #### Basic Usage ```javascript SW.Utils.convertToString(4); SW.Utils.convertToString({first: 1, second: 2}); SW.Utils.convertToString(function () {return 2+2}); ``` #### Response ```javascript "4" "{first: 1,second: 2}" "function () {return 2+2}" ``` --- ## copyToClipboard #### Description This method can be used to save text in the clipboard. #### Method(s) ```javascript 1 function copyToClipboard(text: string): void ``` Parameter Type Required Defaults Description text string false Text to save in clipboard #### Basic Usage ```javascript SW.Utils.copyToClipboard('SkillsWorkflow') ``` #### Response The text "SkillsWorkflow" will be saved in the clipboard --- ## getDataArrayFromMultipleSelectionFieldString #### Description This method can be used to convert a string of data into an array of data. #### Method(s) ```javascript 1 function getDataArrayFromMultipleSelectionFieldString(dataString: string): any[] ``` Parameter Type Required Defaults Description dataString string false String of data to be converted to array #### Basic Usage ```javascript SW.Utils.getDataArrayFromMultipleSelectionFieldString("[{\"name\":\"John\"}, {\"name\":\"Arthur\"}]") ``` #### Response ```javascript [{name: John}, {name: Arthur}] ``` --- ## getEmptyGuidValue #### Description This method can be used to check if parameter key it's a empty guid. #### Method(s) ```javascript 1 function getEmptyGuidValue(key: string, callback: Function): Promise ``` Parameter Type Required Defaults Description key string false Guid value callback Function false Function to be executed case is not empty guid #### Basic Usage ```javascript SW.Utils.getEmptyGuidValue('00000000-0000-0000-0000-000000000000', function () { return "It's empty guid" } ) SW.Utils.getEmptyGuidValue('72917063-915e-4e23-a699-2a6e78804ed', function () { return "It's not empty guid" } ) ``` #### Response ```javascript Promise<{Id: "00000000-0000-0000-0000-000000000000", Name: "N/A"}> "It's not empty guid" ``` --- ## isValidGuid #### Description This method can be used to check if a given guid is valid. #### Method(s) ```javascript 1 function isValidGuid(id: string): boolean ``` Parameter Type Required Defaults Description id string false Guid to check #### Basic Usage ```javascript SW.Utils.isValidGuid('SkillsWorkflow'); SW.Utils.isValidGuid('23814aa4-0b56-4480-8ba8-c02991a5fdca'); ``` #### Response ```javascript false true ``` --- ## setExternalImage #### Description This method can be used to append an image to an html element. #### Method(s) ```javascript 1 function setExternalImage(element: HTMLElement, size: Size, url: string): HTMLElement ``` Parameter Type Required Defaults Description element HTMLElement true Element to append image size Size true MEDIUM Image size url string true Image url #### Basic Usage ```javascript SW.Utils.setExternalImage(element, 'small', 'https://test.com/images/logo_new_small.png'); ``` #### Response The image will be append to the given element. --- --- ## Webhooks URL: https://documentation.skillsworkflow.com/docs/build-and-extend/api/webhooks Summary: Webhooks let you react to events inside Skills Workflow in real time — no polling needed. Webhooks let you react to events inside Skills Workflow in real time — no polling needed. When something happens (a stage changes, a field is updated, a document is created), the platform calls a URL you define or triggers an internal automation. ## Quick Start > **Goal:** Create a webhook that fires an Azure DevOps automation whenever the custom field *"Is Customization"* changes on a User Story deliverable. | Step | Field | Value | |---|---|---| | 1 | **Name** | `Create Work Item when Is Customization is unchecked` | | 2 | **Active** | On | | 3 | **Event** | `UserFieldValueUpdated` | | 4 | **Document** | `Deliverable` | | 5 | **Automation** | On | | 6 | **Automation Workflow** | `Azure DevOps – Create Work Item in Visual Studio` | | 7 | **Business Object Type Name** | `User Story` | | 8 | **Detail Path Expression** | `ColumnName`   **Condition:** `Equal`   **Value:** `Is Customization` | That's it — the webhook is ready. Read on to understand each section of the form. --- ## Using Webhooks with Automations Webhooks can also act as entry points for [Automation Workflows](../automations/). Instead of sending the event to an external URL, enable **Automation** and select an **Automation Workflow** as the destination. Use this pattern when the event should start a controlled workflow: call one or more APIs, map data, generate files, send emails, or return a structured response. The automation can access the webhook request through `{{['#HttpRequest']}}`, including its body, headers, query values and other request context. For the automation model, expression syntax and available actions, see [Automations](../automations/) and the [Actions reference](../automations/actions). --- ## Configuring a Webhook Navigate to **Maintenance > Webhooks** and click **Create New Webhook**. The form is divided into four sections, from top to bottom. Fill them out in order. --- ### 1. General | Field | Description | |---|---| | **Name** | A descriptive title for the webhook. Used internally to identify it. | | **Active** | Toggle to enable or disable the webhook. Only active webhooks fire. | | **Description** | A short explanation of what the webhook does and when it should trigger. | | **Created On / Modified By** | Automatically filled metadata. | --- ### 2. Document This section defines **what** triggers the webhook. #### Event The type of event that should fire the webhook. Choose from the dropdown or type a custom value. | Event | When it fires | |---|---| | `Created` | A document was created. | | `Updated` | A document property was modified. | | `Deleted` | A document was deleted. | | `UserFieldValueUpdated` | A custom (user-defined) field on a document changed. | | `TimeUpdated` | Timesheet data was updated. | | Event | When it fires | |---|---| | `StageUpdated` | The workflow stage of a document changed (state transition). | | Event | When it fires | |---|---| | `LoginSucceeded` | A user logged in successfully. | | `LoginFailed` | A login attempt failed. | | Event | When it fires | |---|---| | `UserRoleAdded` | A role was assigned to a user. | | `UserRoleRemoved` | A role was removed from a user. | | `UserEffectiveRolesChanged` | A user's effective roles changed (hierarchy recalculation). | | `UserImageUpdated` | A user's profile image was updated. | | `RoleAddedToRole` | A child role was added to a role. | | `RoleRemovedFromRole` | A child role was removed from a role. | | `TeamAdded` | A team member was added to a document. | | `TeamRemoved` | A team member was removed from a document. | | Event | When it fires | |---|---| | `BatchExecuted` | A batch operation was executed (e.g., bulk delete). | | `FileDownloaded` | A file was downloaded from the system. | | `Executed` | A generic execution event. | The Event dropdown also accepts **custom values**, so you can type any event name if needed. #### Document Type The entity type the webhook listens to. Loaded from the system and varies per tenant. Full list of document types | Document Type | Full Type Name | |---|---| | Assignment | `Skill.Module.BusinessObjects.Assignment` | | Bill | `Skill.Module.BusinessObjects.Bill` | | Brand | `Skill.Module.BusinessObjects.Brand` | | Client | `Skill.Module.BusinessObjects.Client` | | Client Credit Note | `Skill.Module.BusinessObjects.ClientCreditNote` | | Commercial Client | `Skill.Module.BusinessObjects.CommercialClient` | | Commercial Client Product | `Skill.Module.BusinessObjects.CommercialClientProduct` | | Contract | `Skill.Module.BusinessObjects.Contract` | | Deliverable (Job) | `Skill.Module.BusinessObjects.Deliverable` | | Document Brief | `Skill.Module.BusinessObjects.DocumentBrief` | | Document State | `Skill.Module.BusinessObjects.DocumentState` | | Document Tag | `Skill.Module.BusinessObjects.DocumentTag` | | Document Task | `Skill.Module.BusinessObjects.DocumentTask` | | Estimate | `Skill.Module.BusinessObjects.Estimate` | | Expense | `Skill.Module.BusinessObjects.Expense` | | Expense Item | `Skill.Module.BusinessObjects.ExpenseItem` | | File | `Skill.Module.BusinessObjects.FileSystemObject` | | Job Type | `Skill.Module.BusinessObjects.JobType` | | Lead | `Skill.Module.BusinessObjects.CRM.Lead` | | Person | `Skill.Module.BusinessObjects.Person` | | Project | `Skill.Module.BusinessObjects.Project` | | Purchase Order | `Skill.Module.BusinessObjects.PurchaseOrder` | | Supplier Invoice | `Skill.Module.BusinessObjects.SupplierInvoice` | | Supplier Note | `Skill.Module.BusinessObjects.SupplierNote` | | Supplier Request | `Skill.Module.BusinessObjects.SupplierRequest` | | Task | `Skill.Module.BusinessObjects.Task` | | Tender | `Skill.Module.BusinessObjects.Tender` | | Timesheet | `Skill.Module.BusinessObjects.Timesheet` | | User | `Skill.Module.BusinessObjects.User` | | Workflow State | `Skill.Module.BusinessObjects.WorkflowState` | | Workflow State Transition | `Skill.Module.BusinessObjects.WorkflowStateTransition` | Additional document types may be available depending on your tenant configuration. Use the `GET /api/v3/document-types/lookup` endpoint to retrieve the full list. --- ### 3. Destination Where the webhook sends its payload when triggered. Leave **Automation** toggled off and fill in: - **URL** — The external endpoint to call. _Example:_ `https://example.com/webhooks/my-webhook` Toggle **Automation** on and select: - **Automation Workflow** — The internal integration workflow to run. _Example:_ `Azure DevOps – Create Work Item in Visual Studio` - **Secret** — A key shared with the destination to authenticate the webhook request. --- ### 4. Filters Filters let you narrow **when** the webhook fires. Without filters, every occurrence of the selected Event + Document triggers it. #### Business Object Type Name Optionally limit the webhook to a specific business object type (e.g., `User Story`, `Estimate`). #### Detail Filters Each filter row has four parts: | Part | Description | |---|---| | **Group Condition** | `And` (all filters must match) or `Or` (any filter can match). | | **Detail Path Expression** | The property name inside the event's detail payload to evaluate. | | **Condition** | `Equal`, `NotEqual`, `Contains`, or `NotContains`. | | **Value** | The value to compare against. | Click **+ Add filter** to add more rows. The fields you can use in **Detail Path Expression** depend on the **Event** you selected. Each event type produces a different payload. See the reference below. #### Detail Path Expression Fields per Event Use the tabs below to find the exact field names available for each event type. Fired when a document's workflow stage changes. | Detail Path Expression | Type | Description | |---|---|---| | `WorkflowStageTransitionId` | `guid` | ID of the stage transition. | | `WorkflowStageTransitionName` | `string` | Name of the transition. | | `WorkflowStageTransitionLocalizedName` | `string` | Localized name of the transition. | | `FromWorkflowStageId` | `guid` | ID of the source stage. | | `FromWorkflowStageName` | `string` | Name of the source stage. | | `FromWorkflowStageLocalizedName` | `string` | Localized name of the source stage. | | `ToWorkflowStageId` | `guid` | ID of the destination stage. | | `ToWorkflowStageName` | `string` | Name of the destination stage. | | `ToWorkflowStageLocalizedName` | `string` | Localized name of the destination stage. | | `WorkflowId` | `guid` | ID of the workflow. | | `WorkflowName` | `string` | Name of the workflow. | | `DepartmentId` | `guid` | ID of the department (if applicable). | When the transition is resolved from individual stage objects, the `WorkflowStageTransition*` fields may not be present. **Common example:** | Detail Path Expression | Condition | Value | |---|---|---| | `ToWorkflowStageName` | `Equal` | `Under Development` | Fired when a custom user field value changes on a document. | Detail Path Expression | Type | Description | |---|---|---| | `ColumnName` | `string` | Database name of the user field that changed. | | `Value` | `object` | The new value of the field. | **Common example:** | Detail Path Expression | Condition | Value | |---|---|---| | `ColumnName` | `Equal` | `Is Customization` | Fired when a document is created, updated, or deleted. The payload contains a **dynamic** set of properties — every persistent property that was changed on the document. The exact fields depend on the document type and which properties changed. Examples: | Detail Path Expression | Type | Description | |---|---|---| | `Name` | `string` | Document name (if changed). | | `BeginDate` | `datetime` | Begin date (if changed). | | `EndDate` | `datetime` | End date (if changed). | | _...any document property_ | _varies_ | Any persistent property that was modified. | `TimeUpdated`, `TeamAdded`, `TeamRemoved`, and `RoleAddedToRole` / `RoleRemovedFromRole` also use this same dynamic payload pattern. Fired on `LoginSucceeded` or `LoginFailed`. | Detail Path Expression | Type | Description | |---|---|---| | `LoginType` | `string` | Auth method: `SsoToken`, `Token`, or `RefreshToken`. | | `Username` | `string` | Username of the login attempt. | | `LoginAsDelegate` | `boolean` | Whether the login was an impersonation. | | `DelegatedUserName` | `string` | Delegated username (if applicable). | | `FailureReason` | `string` | Reason for failure (`LoginFailed` only). | **Common example:** | Detail Path Expression | Condition | Value | |---|---|---| | `Username` | `Equal` | `john.doe` | Fired on `UserRoleAdded` or `UserRoleRemoved`. | Detail Path Expression | Type | Description | |---|---|---| | `RoleId` | `string` | ID of the role. | | `RoleName` | `string` | Name of the role. | `UserImageUpdated` and `UserEffectiveRolesChanged` do **not** carry any detail fields. Fired on `BatchExecuted`. | Detail Path Expression | Type | Description | |---|---|---| | `DocumentType` | `string` | Full type name of the business object. | | `Url` | `string` | The API endpoint where the batch ran. | `FileDownloaded` does not have a documented detail-field contract. These events are available but carry **no filterable detail fields**: - `UserImageUpdated` - `UserEffectiveRolesChanged` - `FileDownloaded` - `Executed` They trigger the webhook for every occurrence — no Detail Path Expression filtering is possible. #### Dynamic Filter Values You can use **System Parameters** as dynamic values in the **Value** field. Reference them with: ``` {{SystemPreferenceName/KeyName}} ``` _Example:_ `{{MyAutomationPreferences/departments}}` ```json title="MyAutomationPreferences" { "user": "skills-user", "password": "my-strong-password", "departments": [ "6f51b21e-2dcc-4f5e-aebb-491b54800bf1", "a733e914-18ea-4c92-94b4-59491badc974", "ecc30504-1f5c-4b3b-a864-da85d04ebabe", "d42168e4-f690-4546-8197-54ba344a1806" ] } ``` --- ## Examples ### Trigger when a custom field changes Fire a webhook when *"Is Customization"* changes on a deliverable, filtered to the User Story business object type: | Field | Value | |---|---| | Event | `UserFieldValueUpdated` | | Document | `Deliverable` | | Business Object Type Name | `User Story` | | Detail Path Expression | `ColumnName` | | Condition | `Equal` | | Value | `Is Customization` | ### Trigger on a stage transition Fire a webhook when a deliverable moves to "Under Development": | Field | Value | |---|---| | Event | `StageUpdated` | | Document | `Deliverable` | | Detail Path Expression | `ToWorkflowStageName` | | Condition | `Equal` | | Value | `Under Development` | ### Trigger on login failure Fire a webhook when a specific user fails to log in: | Field | Value | |---|---| | Event | `LoginFailed` | | Detail Path Expression | `Username` | | Condition | `Equal` | | Value | `john.doe` | ### Multiple filters with AND logic Trigger only when a deliverable's custom field *"Priority"* is set to "High": | # | Group Condition | Detail Path Expression | Condition | Value | |---|---|---|---|---| | 1 | And | `ColumnName` | `Equal` | `Priority` | | 2 | And | `Value` | `Equal` | `High` | --- ## API Reference Webhook subscriptions can also be managed via REST API. Base URL: `/api/webhook-subscriptions` Endpoints #### List All Webhooks ```http GET /api/webhook-subscriptions ``` Returns all webhook subscriptions for the current tenant. **Response:** `200 OK` — Array of `WebhookSubscription` objects. #### Get Webhook by ID ```http GET /api/webhook-subscriptions/{id} ``` | Parameter | Type | Description | |---|---|---| | `id` | `guid` | The webhook subscription ID. | **Response:** `200 OK` — A single `WebhookSubscription` object. #### Create Webhook ```http POST /api/webhook-subscriptions ``` **Request Body:** ```json { "Name": "My Webhook", "Description": "Triggers when a deliverable is created", "ActionType": "Created", "DocumentType": "Skill.Module.BusinessObjects.Deliverable", "Url": "https://example.com/webhook-endpoint", "Secret": "my-secret-key", "Active": true, "IsAutomation": false, "AutomationId": null, "BusinessObjectTypeName": null, "DetailFilters": [ { "groupCondition": "And", "jsonPathExpression": "ColumnName", "condition": "Equal", "value": "Priority" } ] } ``` | Field | Type | Required | Description | |---|---|---|---| | `Name` | `string` | Yes | Display name of the webhook. | | `Description` | `string` | No | Purpose description. | | `ActionType` | `string` | Yes | The event type (e.g., `Created`, `StageUpdated`). | | `DocumentType` | `string` | Yes | Full type name (e.g., `Skill.Module.BusinessObjects.Deliverable`). | | `Url` | `string` | Yes* | Destination URL. Required unless `IsAutomation` is `true`. | | `Secret` | `string` | No | Secret key for request authentication. | | `Active` | `boolean` | No | Whether the webhook is enabled. Defaults to `false`. | | `IsAutomation` | `boolean` | No | `true` to trigger an internal automation instead of a URL. | | `AutomationId` | `guid` | No | ID of the automation workflow. Required when `IsAutomation` is `true`. | | `BusinessObjectTypeName` | `string` | No | Filter by business object type name. | | `DetailFilters` | `array` | No | Array of detail filter objects. | **DetailFilter object:** | Field | Type | Description | |---|---|---| | `groupCondition` | `string` | `And` or `Or`. | | `jsonPathExpression` | `string` | The property name to evaluate in the event detail payload. | | `condition` | `string` | `Equal`, `NotEqual`, `Contains`, `NotContains`. | | `value` | `string` | The value to compare against. | **Response:** `201 Created` #### Update Webhook ```http PUT /api/webhook-subscriptions/{id} ``` Same body as Create. **Response:** `200 OK` #### Delete Webhook ```http DELETE /api/webhook-subscriptions/{id} ``` **Response:** `200 OK` #### Get Invocation History ```http GET /api/webhook-subscriptions/{id}/invocation-history ``` | Parameter | Type | Required | Description | |---|---|---|---| | `id` | `guid` | Yes | Webhook subscription ID. | | `fromDateUtc` | `datetime` | No | Start date filter (UTC). | | `toDateUtc` | `datetime` | No | End date filter (UTC). | | `take` | `int` | No | Number of records (default: 100). | | `continuationToken` | `string` | No | Pagination token. | **Response:** `200 OK` — Array of invocation records. Response Object ```json { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "tenantId": "c8d054c7-9933-4b6d-9e55-66ed1ba9526d", "name": "My Webhook", "description": "Triggers when a deliverable is created", "url": "https://example.com/webhook-endpoint", "secret": "my-secret-key", "actionType": "Created", "documentType": "Skill.Module.BusinessObjects.Deliverable", "active": true, "createdOnUtc": "2026-04-08T12:00:00Z", "createdById": "315d6513-3418-4369-8e87-c204316c27c2", "modifiedOnUtc": "2026-04-08T12:00:00Z", "modifiedById": "315d6513-3418-4369-8e87-c204316c27c2" } ``` ### Required Permissions | Operation | Required Role | |---|---| | List / Get | `WebhookSubscriptionGet` | | Create | `WebhookSubscriptionCreate` | | Update | `WebhookSubscriptionWrite` | | Delete | `WebhookSubscriptionDelete` | | Navigate (UI) | `WebhookSubscriptionNavigate` | --- ## Workflow structure URL: https://documentation.skillsworkflow.com/docs/build-and-extend/automations/workflow-structure Summary: The shape of an Automation Workflow: the fields on the workflow itself, how actions chain through next, the rules that must hold before it saves, sub-workflows and error routing. A workflow is a JSON document holding a list of actions. The builder draws it, but knowing the underlying shape is what lets you read an exported workflow or work out why one refuses to save. ## The workflow ```json title="The envelope, with the actions omitted" { "id": "guid", "tenantId": "guid", "name": "SyncSuppliers", "active": true, "version": 1, "logLevelType": "Info", "requiresAuthentication": false, "actions": [], "subWorkflows": [], "scheduler": null } ``` | Field | Meaning | |---|---| | `name` | Required, and cannot be empty. | | `active` | Whether the workflow is eligible to run. | | `version` | Incremented as the workflow is edited. | | `logLevelType` | `Info`, `Warning` or `Error`. Set it against how critical the workflow is. | | `requiresAuthentication` | Whether an inbound call must be authenticated. | | `actions` | The chain. See below. | | `subWorkflows` | Named action chains this workflow can call. | | `scheduler` | Present only on scheduled workflows. See [How automations start](./triggers.md#schedules). | ## Chaining actions Every action carries an `actionType` and a `name`, and the `name` is how the rest of the workflow refers to it. Non-terminal actions carry `next`, naming the action that runs after them. ```json { "actionType": "Start", "name": "Start", "next": "FetchSuppliers" } { "actionType": "Rest", "name": "FetchSuppliers", "next": "Exit", "method": "GET", "url": "..." } { "actionType": "Result", "name": "Exit" } ``` Branching works differently: [`Case`](./actions-reference.md#case) replaces `next` with `nextActions`, a list of candidate branches, and one of them may be marked `{ "default": true }`. ## Rules a workflow must satisfy These are checked when the workflow is saved. A workflow that breaks any of them is rejected. - Exactly one `Start` action. - At least one `Result` action. - Action names are unique within the workflow, and within each sub-workflow. - Every `next` names an action that exists. - `Result` must not carry `next`. - No cycle without a way out. Scheduled workflows add their own rules, listed under [Schedules](./triggers.md#schedules). ## Sub-workflows A sub-workflow is a named chain kept beside the main one and called by [`ExecuteSubWorkflow`](./actions-reference.md#executesubworkflow) or run per item by [`Loop`](./actions-reference.md#loop). It follows the same rules as the workflow: its own `Start`, its own `Result`, unique names inside it. ```json title="An empty sub-workflow, ready to fill in" { "name": "CreateProjectIfNotExists", "actions": [ { "actionType": "Start", "name": "Start", "next": "Exit" }, { "actionType": "Result", "name": "Exit", "httpResponse": { "statusCode": 200, "headers": { "content-type": "application/json" }, "body": "" } } ] } ``` Reach for one when the same few actions repeat, and whenever you need `Loop`, which runs a sub-workflow per element. ## When an action fails Some actions accept `nextOnError` alongside `next`. When the action fails, the chain continues at the action `nextOnError` names instead of stopping. Use it for failures you can recover from: fall back to a default, log and carry on, or return a considered error from `Result`. Without `nextOnError`, a failing action ends the run. ## Practices worth keeping Keep only the fields an action needs, and drop the ones left null. An exported workflow full of unused properties is hard to read and hides the fields that matter. Give `Case` a default branch. Without one, an unmatched test is a dead end. Name actions after what they do rather than what they are. `FetchSuppliers` tells the next reader more than `Rest1`, and the name is what every expression downstream will quote. ## Related articles - [Actions](./actions-reference.md) - [Expressions](./expressions/index.md) - [How automations start](./triggers.md) --- ## Workspace URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/application/application-workspace Summary: This method can be used inside any workspace. ## refresh #### Description This method can be used inside any workspace. Refresh a workspace #### Method(s) ```javascript 1 declare function refresh(): void; ``` #### Basic Usage ```javascript SW.Application.Workspace.refresh(); ``` ## setFilter #### Description This method can be used inside any workspace. Create a new assignment #### Method(s) ```javascript 1 declare function setFilter(filter: string, value: any, 2 params: {senderId?: string} = {senderId: ""}): void; ``` Parameter Type Required Defaults Description filter String true value Any true senderId String false "" Sender's id #### Basic Usage ```javascript SW.Application.Workspace.setFilter(filter, 20); ``` ## setFilters #### Description This method can be used inside any workspace. Set multiple filters #### Method(s) ```javascript 1 declare function setFilters(filtersWithValues: DashboardFilter[], 2 params: {senderId?: string} = {senderId: ""}): void; ``` Parameter Type Required Defaults Description filtersWithValues DashboardFilter true Array of filters senderId String false #### Basic Usage ```javascript SW.Application.Workspace.setFilters([filters], "98226093-09B6-4E12-B9C6-2AEED2963C31"); ``` Example ```javascript {12} { name: "apply", itemType: "button", buttonOptions: { width: 100, text: "Apply", onClick: function () { var from = workspaceContext.get("From").option("value"); var to = workspaceContext.get("To").option("value"); var includeNew = workspaceContext.get("IncludeNew").option("value"); workspaceContext.set("Loading", Date.now()); SW.Application.Workspace.setFilters([{ Name: "From", Value: Date.now() }, { Name: "To", Value: Date.now() }]); SW.Application.Workspace.setFilters([{ Name: "From", Value: from }, { Name: "To", Value: to }, { Name: "IncludeNew", Value: includeNew }]); } } }, ``` ## setPanels #### Description This method can be used inside any workspace. Set workspace's panels #### Method(s) ```javascript 1 declare function setPanels(items: IUpdatedLayoutItems, 2 options: ILayoutEditOptions): void; ``` Parameter Type Required Defaults Description items IUpdatedLayoutItems[] true Layout items to be updated. Pass the name or id of the item.x: Moves the panel horizontallyy: Moves the panel verticallycols: Sets the number of columnsrows: Sets the number of rows options ILayoutEditOptions true A boolean to set save option to true or false #### Basic Usage ```javascript SW.Application.Workspace.setPanels({ GridName1: { x: 0, y: 0, cols: 10, rows: 10 }, 'Grid Name 2': { x: 10, y: 2, cols: 10, rows: 10 } }) ``` ## getParameter #### Description Retrieves the value of a specified parameter from the workspace. #### Method(s) ```javascript 1 declare function getParameter(name: string): any; ``` Parameter Type Required Defaults Description name string[] true The name of the parameter to fetch the value from. #### Basic Usage ```javascript SW.Application.Workspace.getParameter('parameterName') ``` --- ## Workspace Context URL: https://documentation.skillsworkflow.com/docs/build-and-extend/workspaces/panels/workspace-context Summary: All of the workspaces have the possibility to access the context, where it is possible to find the info of the components, the workspace and perform… All of the workspaces have the possibility to access the context, where it is possible to find the info of the components, the workspace and perform operations like get, set and subscribe Can have access in two ways: 1. Clicking on the button "set default value", and shows the default parameters of the functions, that includes the workspaceContext 2. If a function already exists and the context parameter isn't declared, it could be added manually. WorkspaceContext is a function that has three main properties: - Set - Get - Subscribe - Definition - ComponentDefinition It allows you to set a context variable in a workspace and access that variable in another workspace under the same routing scope. --- ### Set Used to set the the value in a variable to use posteriorly Parameter Type Required Description name String true Name to reference the valued passed value Any true Any type of value can be passed ```js workspaceContext.set("name", value); ``` Variable updateClient set at function onInitialized, to save the component --- ### Get Used to get the value saved previously Parameter Type Required Description name String true Name of the reference passed previously ```js workspaceContext.get("name"); ``` Getting the value saved at variable updateClient --- ### Subscribe Subscribe the context's variable you want to listen Parameter Type Required Description name String true Name to reference the passed value callBack String true A callBack function # ```js workspaceContext.get('name', callBack function(){}); ``` - Subscribe the variable updateClient defined at the beggining. In this case the value was used to show a pop-up if the client exists - Use the new value to make the necessary changes everytime the variable value is updated. ::: --- ## Workspaces URL: https://documentation.skillsworkflow.com/docs/build-and-extend/sdk/workspaces Summary: All settings directly regarding workspaces configuration properties (advanced) All the workspaces configuration functions have context as last parameter. ## info All settings directly regarding workspaces configuration properties (advanced) ## contextParameter ### Description All the workspaces configuration functions have context as last parameter. Context is of type function and has 3 properties. Set, Get and Subscribe. It allows you set a context variable in workspace and access that variable in another workspace under the same routing scope. ### Typical function ```js {3} 1 function onPointClick(e, context){ } ``` ### Set ```js {3} 1 context.set('name', value); ``` Parameter Type Required Defaults Description name String true Name to reference the passed value value any true Any type of value can be passed ### Basic Usage Variable ExecutorName set on workspace A ### Get ```js {3} 1 context.get('name'); ``` Parameter Type Required Defaults Description name String true Name to reference the passed value ### Basic Usage Get used on workspace B to access variable ExecutorName previously set on Workspace A ### Subscribe Subscribe context's variable you want to listen ```js {3} 1 context.get('name', callBack function); ``` Parameter Type Required Defaults Description name String true Name to reference the passed value callBack String true A callBack function ### Basic Usage Subscribe to variable previously set on worspace A. Use the new value to make the necessary changes everytime the variable value is updated. --- ## Workspaces URL: https://documentation.skillsworkflow.com/docs/build-and-extend/workspaces Summary: Click on the add icon to open the creation pop-up. To create workspace, navigate to the **Workspaces** in the Configuration. ## Creating workspaces in Configuration 1. Click on the add icon to open the creation pop-up. 2. Fill the fields. Name, Location and Platform fields are required. Parameter Required Description Name true Name you want to give the Workspace Location true Where to wish place the Workspace Platform true Select in which Platform Type false Select a default type/category Default false To set the workspace as Default Version false Workspace's version, is set to 1 by default Active false If it's active # Learning paths --- ## Administering a client URL: https://documentation.skillsworkflow.com/docs/learning-paths/administrator Summary: An ordered route through the configuration an administrator needs: users, profiles, workflows, calendars, custom tables and data imports. # Administering a client The order a client is usually set up in. Each step is configuration that later steps depend on, so it is worth following the sequence the first time through. ## Understand the model first 1. [Glossary](/docs/start-here/glossary) — the terms the configuration screens use. 2. [Roles and profiles](/docs/administration/system-roles-profiles) — how access is granted, and the vocabulary the rest of this route assumes. ## People 3. [Create a user](/docs/administration/users/create-user) 4. [Edit a profile](/docs/administration/users/edit-profile) — what a profile controls. 5. [Password policy](/docs/administration/users/password-policy) 6. [Teams and groups](/docs/product/people/teams/what-is-a-team) — how work is distributed once the users exist. ## Calendars 7. [Holidays](/docs/administration/calendars/create-holidays) — these affect scheduling, so set them before anyone plans against a calendar. 8. [Leave types](/docs/administration/calendars/create-leave-type) 9. [Absence types](/docs/administration/calendars/create-assign-type) ## Workflows 10. [Workflows](/docs/administration/workflows) — how documents move through their lifecycle. 11. [Stages](/docs/administration/workflows/stages) and [stage types](/docs/administration/workflows/stage-types) 12. [Transitions](/docs/administration/workflows/transitions) — the rules, roles and actions that run when a document moves. 13. [Stage mappings](/docs/administration/workflows/stage-mappings) ## Data 14. [Typologies](/docs/administration/create-typologies) — the classification the rest of the data hangs from. 15. [Custom tables](/docs/administration/custom-tables) — extending the data model. 16. [Importing data](/docs/administration/importing-data/users) — bringing users, departments, employees and projects in. ## System 17. [Menu](/docs/administration/system/menu) — what each profile sees. 18. [Custom style](/docs/administration/system/customstyle) — branding. 19. [Query mentions](/docs/administration/system/queryMentions) ## Where to go next - [Using the platform](./end-user.md), to understand what the people you configured for actually do. - [Implementing the platform](./consultant.md), for workspaces, automations and the API. --- ## Get started URL: https://documentation.skillsworkflow.com/docs/learning-paths Summary: Ordered routes through the Skills Workflow documentation for the person using the platform, the person administering it, and the person implementing it. # Get started Three routes through the documentation, each in the order the work is actually done. Every step links to the same page the rest of the documentation uses. Nothing is written twice, so no page can be current on one route and stale on another. | Route | For | Starts with | | --- | --- | --- | | [Using the platform](/docs/learning-paths/end-user) | Anyone doing the work | Creating a project | | [Administering a client](/docs/learning-paths/administrator) | Administrators | Users and profiles | | [Implementing the platform](/docs/learning-paths/consultant) | Consultants and developers | Workspaces | You do not have to start at the beginning. Each step says what it covers, so you can join a route wherever your question is. --- ## Implementing the platform URL: https://documentation.skillsworkflow.com/docs/learning-paths/consultant Summary: An ordered route for consultants and developers: workspaces, panels, automations, the SDK and the API. # Implementing the platform For the people who configure and extend Skills Workflow for a client. This route assumes you already understand what the client's users do. If you do not, start with [Using the platform](./end-user.md) — the same pages their users read. ## Ground yourself first 1. [Glossary](/docs/start-here/glossary) — including where the interface and the API use different names for the same thing. 2. [Administering a client](./administrator.md) — the configuration everything below sits on. ## Workspaces 3. [Workspaces](/docs/build-and-extend/workspaces) — what a workspace is and what it controls. 4. [Definition](/docs/build-and-extend/workspaces/EditWorkspace) — how one is described. 5. [Edit layout](/docs/build-and-extend/workspaces/EditLayout) 6. [Roles](/docs/build-and-extend/workspaces/Roles) — who sees which workspace. ## Panels 7. [Workspace context](/docs/build-and-extend/workspaces/panels/workspace-context) — what a panel can read from around it. 8. [Grid: set columns](/docs/build-and-extend/workspaces/panels/set-columns) — the largest and most used panel reference. 9. [Grid: inline editing](/docs/build-and-extend/workspaces/panels/allow-inline) 10. [Form: set items](/docs/build-and-extend/workspaces/panels/set-items) 11. [Datasource: store](/docs/build-and-extend/workspaces/panels/store) and [endpoint](/docs/build-and-extend/workspaces/panels/endpoint) — where a panel's data comes from. ## Automations 12. [Automations](/docs/build-and-extend/automations) — the model and when to reach for it. 13. [Build your first automation](/docs/build-and-extend/automations/getting-started) 14. [Actions reference](/docs/build-and-extend/automations/actions) — every action, its inputs and its output. 15. [Recipes](/docs/build-and-extend/automations/recipes/recipe-export-to-csv) — complete automations to adapt. ## Code 16. [SDK](/docs/build-and-extend/sdk) — what is callable from a workspace. 17. [Client API](/docs/build-and-extend/api/client-api) 18. [Webhooks](/docs/build-and-extend/api/webhooks) — events out, and the entry point for automations. 19. [Data extraction](/docs/build-and-extend/api/data-extraction-api) — the reporting interface. ## Connecting other systems 20. [Integrations](/docs/integrations) — what already exists before you build anything. ## AI 21. [AI Assistant](/docs/ai/ai-assistant) — what the client's users see, and the four settings that control it. 22. [Agents](/docs/ai/agents) — which agent handles which kind of request. 23. [Tools](/docs/ai/ai-tools) — what an agent can read and change, and which actions ask for approval. 24. [Add your own skills, agents and tools](/docs/ai/ai-extend) — configuring AI around a client's own way of working. 25. [AI Actions](/docs/ai/ai-actions) — the editor actions, which a client defines themselves. 26. [Client Portals](/docs/ai/ai-portals) — a page of a client's own, generated with AI. --- ## Using the platform URL: https://documentation.skillsworkflow.com/docs/learning-paths/end-user Summary: An ordered route through Skills Workflow for the people doing the work: projects, jobs, planning, time and approvals. # Using the platform The order a project actually moves in, from the brief arriving to the hours being approved. ## Before you start 1. [Glossary](/docs/start-here/glossary) — the words the interface and the API use, including the cases where they disagree. 2. [Roles and profiles](/docs/administration/system-roles-profiles) — what you can see and do depends on your profile. 3. [Favorites](/docs/product/favorites) — getting back to the work you care about. ## Set the work up 4. [Client requests](/docs/product/briefing-and-requests/create-client-requests) — how work arrives from a client. 5. [Create a project](/docs/product/projects-and-jobs/create-projects) — the container everything else hangs from. 6. [Create jobs](/docs/product/projects-and-jobs/create-jobs) — breaking the project into the work that gets assigned. ## Plan it 7. [Using the Gantt](/docs/product/planning-and-scheduling/gantt) — dates, dependencies and the shape of the schedule. 8. [Resource scheduler](/docs/product/planning-and-scheduling/resourcing/resource-scheduler) — who is available, and for what. 9. [Assign an executor](/docs/product/people/teams/what-is-a-team) — putting a name against the work. 10. [Planned Time](/docs/product/planning-and-scheduling/resourcing/planned-hours) — how much time the work is expected to take. ## Do it and report it 11. [Filling in timesheets](/docs/product/time/timesheets/filling-time-sheets) — recording the hours. 12. [Timesheet timer](/docs/product/time/timesheets/timesheet-timer) — recording them as they happen instead. 13. [Annotations](/docs/product/files-and-collaboration/annotations) — reviewing files with feedback on the file itself. 14. [The feed](/docs/product/files-and-collaboration/using-feed) — where the conversation about a document lives. ## Follow it 15. [My tasks](/docs/product/projects-and-jobs/my-tasks) — your own queue. 16. [List view](/docs/product/projects-and-jobs/list-view) — filtering and shaping any list of documents. 17. [Approving timesheets](/docs/product/time/timesheets/approving-time-sheets) — for anyone who approves rather than submits. ## Where to go next - [Administering a client](./administrator.md), if you also configure the platform. - [Dashboards and reporting](/docs/product/dashboards-and-reporting) for the numbers behind all of the above. # Product --- ## Android App User Configuration URL: https://documentation.skillsworkflow.com/docs/product/mobile/android-configuration Summary: Downloading the Skills Workflow app from the Play Store and configuring it on an Android device. To configure your Skills Workflow on Android, first you will need to download our app from the Play Store. To configure the app you should follow these few steps: - Open SkillsWorkflow App - On the Login Page tap on the Settings icon in the bottom right corner - Fill the site name given by your manager: (Ex: https://demo.skillsworkflow.com) - Select the Environment and Save ## Related articles - [Mobile Features](/docs/product/mobile/mobile-features) - [iOS App User Configuration](/docs/product/mobile/ios-app-config) --- ## Annotations URL: https://documentation.skillsworkflow.com/docs/product/files-and-collaboration/annotations Summary: Annotation features in the Skills Workflow file preview. # Annotations Annotations let users place visual feedback directly on file previews. In Skills Workflow, annotations are available for images, videos, and PDFs when the feature is enabled. ## File preview annotations Annotations appear in the file preview side panel under the **Annotations** module. The module is only shown when annotations are enabled and the current file can be annotated. The **+** button in the **Annotations** module starts a new annotation. Clicking the module title/header does not start the editor. For videos, the **+** button is available after the preview's metadata has loaded. For PDFs, it is available after a PDF page has rendered. Supported file previews: - Images. - Videos. - PDFs. Annotations module in the file preview ## Annotation toolbar The annotation toolbar is shown inside the **Annotations** module while the annotation editor is active. The toolbar provides undo/redo, Frame, Ellipse, Arrow, Line, Freehand, Highlight, and a color dropdown. Save and Cancel are shown in the annotation card when editing a comment, or below the toolbar when no annotation card is being edited. Annotation toolbar inside the Annotations module ## Comments and side panel Each annotation card shows the author, date/time, comment text, video timestamp when applicable, PDF page number when applicable, and a history indicator when previous text versions exist. On the preview, annotations with a comment also show a short comment label beside their marker. Selecting an annotation in the side panel opens it on the preview. Selecting another user's annotation shows it, but does not show the inline editor. When an annotation is selected or hovered, Skills Workflow visually links the annotation card to the marker on the preview with a connector line. Hovering a card highlights the related marker without changing the current selection. If another annotation is already selected, the selected connector remains visible but muted. Annotation card in the side panel ## Editing rules The edit rule is per annotation: - Users can edit/delete their own annotations. - Users cannot edit/delete annotations created by another user. - A new annotation belongs to the user who drew it. - Editing annotation text records the previous text in the annotation history. - Saving a comment closes the annotation editor. - Cancelling reloads the last saved annotation state and discards work in progress. ## Unsaved changes When closing the preview while the annotation editor is active, the user chooses between Save and close, Discard annotations, or Keep editing. Unsaved annotations dialog ## Video behavior Video annotations are tied to a timestamp. Existing annotations appear over the video when playback is near the stored timestamp, timeline ticks show where annotations exist, and clicking a tick seeks the video to that timestamp. Opening the editor freezes the video frame so the annotation is drawn on a stable image. Video annotation timeline ## PDF behavior PDF annotations are associated with the page where they were created. When users move between PDF pages, the annotations remain linked to the correct page. PDF page annotation ## Collaboration and feed Users who do not own the file can add annotations to the original file. Annotations from different reviewers are kept together on that file. When a reviewer closes the preview after saving annotations, Skills Workflow creates a feed post that references the reviewed file and includes the review comments. Feed post created after annotations are saved ## Configuration To enable annotations for a client: 1. Open **Maintenance**. 2. Go to **Configurations**. 3. Open the **Settings** tab. 4. In the **Features** area, enable **Enable annotations**. 5. Save the configuration. Enable annotations setting Configuration notes: - PDF page approval is a separate feature and is not required to use annotations. - If users cannot see the annotation panel after activation, confirm that **Enable annotations** is enabled and that the file is shown in a supported preview. ## Related articles - [Using the Feed](/docs/product/files-and-collaboration/using-feed) --- ## Approve Expenses URL: https://documentation.skillsworkflow.com/docs/product/billing-and-costs/expenses/approve-expenses Summary: Change the expense sheet stage. ### Expenses can be approved in two ways: - By the project's responsible - By the user's responsible 1. Go the Expense Sheets module. 2. Select All list. 3. Select the expense sheet you want to approve. Change the expense sheet stage. In case the expense sheet is rejected the system will ask for a disapproval reason. A notification will be sent to the requester. ### Approved by the user's responsible 1. Go the Expense module. 2. Select Approve list. 3. Click on the expense you which to approve and check the receipt attached, add a comment and change the stage to approved or disapproved. ### Approved by the project's responsible To approve expenses navigate to Project module and select a project. 1. Go the the expenses tab 2. Click on the expenses you which to visualize and change the stage to approved or disaproved ## Related articles - [Create Expenses](/docs/product/billing-and-costs/expenses/create-expenses) - [Expense Sheets](/docs/product/billing-and-costs/expenses/expense-sheets) --- ## Approving Leaves URL: https://documentation.skillsworkflow.com/docs/product/people/leaves/approving-leaves Summary: To approve/disapprove leaves, navigate to the “Approval” module. Navigate to the **Leaves module**. ## Check which users have leaves to approve 1. The calendar shows an overview of the leaves to approve, with each user representing a different color. 2. Verify that when two users submit leaves to approve on the same day, the day is colored in black on the calendar. 3. You will find a detailed list of leaves to approve by user, on the right side of the calendar. 4. Click on the arrow next to the user’s name to expand the information about the days and type of leave it regards to. ## Approve a Leave 1. Use the fields on the right to filter the leaves to approve for a certain period, department, user, type of leave, and leave status. 2. To approve all leaves for all users at once, click on check button just above the table. 3. To approve all leaves for a certain user click on the check button next to each user. 4. To approve particular leaves expand the information for the user and click on the Ok button for each entry. 5. Verify that the leaves with a leave form are marked with a yellow triangle on the corner of the cell and click on it to open the form. ## Disapprove a Leave 1. Use the fields on the right to filter the leaves to disapprove for a certain period, department, user, type of leave, and leave status. 2. To disapprove all leaves for all users at once, click on the "x" button just above the table. 3. To disapprove all leaves for a certain user click on the "x" button next to each user. 4. To disapprove particular leaves expand the information for the user and click on the cross button for each entry. ## Provide a rejection motive You can provide the user with a motive for rejecting his leave. ## Revise rejected leaves 1. When a supervisor rejects a leave, the user will be notified that the leave has been disapproved and that he needs to revise and submit for approval again. 2. Verify that the users receives the rejection motive. ## Related articles - [Scheduling Leaves](/docs/product/people/leaves/scheduling-leaves) - [Leaves Workspace](/docs/product/dashboards-and-reporting/leave-dashboard) - [Leaves My Department Workspace](/docs/product/dashboards-and-reporting/leave-department-dashboard) --- ## Approving Time Sheets URL: https://documentation.skillsworkflow.com/docs/product/time/timesheets/approving-timesheets Summary: You can approve all the requested timesheets by clicking check icon in the right upper side. Go to workspace **Time sheets Approval** 2. Approve a group by clicking the check icon on the group bar. 3. Approve only the selected by clicking check icon in the right upper side after you select the intended timesheets. 4. The approved timesheets will have a darker green ## Related articles - [Rejecting Time Sheets](/docs/product/time/timesheets/rejecting-time-sheets) - [Time Sheet Approval Levels](/docs/product/time/timesheets/multi-approving-time-sheets) - [Missing Time Hours and Approvals Workspace](/docs/product/dashboards-and-reporting/timesheet-approvals-dashboard) --- ## Billing & Costs URL: https://documentation.skillsworkflow.com/docs/product/billing-and-costs Summary: Turning delivered work into invoices, and recording what it cost. # Billing & Costs The money side of delivery. Invoice authorizations request that a client be invoiced; credit notes correct an invoice downwards. Purchase orders commit to buying from a supplier. Expenses and expense sheets record what the team spent along the way. --- ## Bills URL: https://documentation.skillsworkflow.com/docs/product/billing-and-costs/billing/bills Summary: A Bill is the billing document issued to a client, carrying its own dates and moving through a workflow like other documents in Skills Workflow. # Bills A Bill is the billing document raised against a client. It is its own area in the main menu, and it moves through the stages configured for its workflow like the other documents in Skills Workflow. ## Availability Opening Bills needs the **BillNavigate** permission; viewing a bill needs **BillRead**, creating one needs **BillCreate**, and editing one needs **BillWrite**. ## Working with a bill A bill's own fields are its **Name**, **Date**, **Management Date**, **Due** and **Stage**. A bill also has **Info**, **Files** and **Feed** sections, and can carry workspaces, like other documents in Skills Workflow. ## Related articles - [Invoice Authorizations](/docs/product/billing-and-costs/billing/invoice-authorizations) - [Credit Notes](/docs/product/billing-and-costs/billing/credit-notes) - [Supplier Invoices](/docs/product/billing-and-costs/billing/supplier-invoices) --- ## Briefing & Requests URL: https://documentation.skillsworkflow.com/docs/product/briefing-and-requests Summary: How work reaches the agency: the requests clients raise and what happens to them next. # Briefing & Requests How work reaches the agency. A client raises a request, and from there it becomes the projects and jobs the team delivers. For the templates that shape what a requester is asked to fill in, see [Description Templates](/docs/administration/description-templates) under Administration. --- ## Burn and Utilization Workspace URL: https://documentation.skillsworkflow.com/docs/product/dashboards-and-reporting/burn-and-utilization Summary: Workspaces are a powerful feature used to quickly support decisions related to a specific contract. Workspaces are a powerful feature used to quickly support decisions related to a specific contract. The goal is to give the user the ability to control processes in a very friendly and comprehensive way. As a project manager, it is very useful to understand the status of a specific client and control the profitability of each project and contract. This way the PM will have the necessary tools to negotiate with their clients. There are several workspaces at the Contract-level available in the system that will display different information. Burn and Utilization - Fee 1. Select the contract you want to analyze. 2. Click on the "Burn and Utilization - Fee" tab. The first part provides a summary total for all projects mapped to the fee of the following: 1. Actual Hours – actual timesheet hours logged to each project to date 2. Planned Hours – planned hours for each project 3. Contracted Hours – contracted/sold hours per fee proposal 4. Actual $ - actual hours valued using Rate Card assigned to the Fee Proposal 5. Planned $ - planned hours valued using Rate Card assigned to the Fee Proposal 6. Contracted $ - contracted/sold hours valued using Rate Card assigned to the Fee Proposal 7. % Contracted $ - (Actual $ / Contracted $) x 100 The second part shows the breakdown listing per Project classified and grouped according to Project Stage. Header Filter, Export and Column Chooser features are available for this list. Burn and Utilization Per Role - Fee Click on the "Burn and Utilization Per Role - Fee" tab; The first part provides a summary total for all typology groups quoted in the fee and/or logged actual hours to the projects mapped to the fee of the following: 1. Actual Hours – actual timesheet hours logged to each project to date 2. Planned Hours – planned hours for each project 3. Contracted Hours – contracted hours of the fee proposal 4. Actual $ - actual hours valued using actual rates per user 5. Planned $ - planned hours valued using Rate Card assigned to the Fee Proposal 6. Contracted $ - contracted hours valued using Rate Card assigned to the Fee Proposal 7. % Contracted $ - (Actual $ / Contracted $) x 100 The second part shows the breakdown listing per Typology Group per Department. Header Filter, Export and Column Chooser features are available for this list. #### Monthly Distribution Dollars – A time graph showing Revenue and Cost per Month Hours – A time graph showing Contracted, Forecast and Actual Hours per Month #### Contribution by Typology Group A pie chart showing the breakdown of actual hours by Typology Group #### Utilization by Typology Group This representation will allow you to check if the planned hours or actual hours are burning the contracted hours you have previously sold to your client. #### Utilization by User Also, you will be able to check which user is filling in more hours under your contract. ## Related articles - [Planned Time](/docs/product/planning-and-scheduling/resourcing/planned-hours) - [Filling in Time Sheets](/docs/product/time/timesheets/filling-time-sheets) --- ## Chat URL: https://documentation.skillsworkflow.com/docs/product/files-and-collaboration/chat Summary: Send direct and group messages to colleagues from any screen in Skills Workflow. Chat is the messaging panel inside Skills Workflow. It opens over the screen you are working on and holds your direct and group conversations, the people you are allowed to message, and who is online. ## Availability The chat icon is in the top menu. It appears when chat is active for your company and your profile includes the **ChatNavigate** role. A badge on the icon counts the conversations with unread messages. If chat is active but the service cannot be reached, the panel shows **Chat is unavailable** in place of your conversations. ## Find a conversation or a person The panel has two tabs. **Conversations** lists the conversations you belong to, most recent activity first. Every row carries the participants' picture, the conversation name, when the last message arrived, a preview of it, and how many messages you have not read. The search box matches conversation names. **Users** lists the people you can message, with their typology group and a green dot while they are online. Selecting a person opens the conversation with them. You can also start a conversation from a person's picture wherever it appears with the chat option — for example, in a Feed post, a reply, or a team assignment. ## Start a conversation To message one person, open the **Users** tab and select them. When you have talked before, the existing conversation opens with its history. Two people always share a single conversation. To create a group, use the new conversation button beside the tabs: 1. Select at least two people. Each one appears as a chip above the list and can be removed there. 2. Type a name if you want one. 3. Select **Start conversation**. The name is optional and can be changed later. An unnamed group is listed under the names of its first three members in alphabetical order, followed by the number of members left. ## Write and send Write in the composer at the bottom of the conversation. **Enter** sends the message and **Shift+Enter** starts a new line. Any link you paste becomes clickable and opens in a new tab. If you start writing a message and don't send it, it's still there the next time you open that conversation — but only on this device. While a message is on its way it shows **Sending...**. If it does not reach the service, it stays on screen as **Message not sent** with a **Retry** action. Messages sent one after another by the same person are grouped together, with the time shown once at the end of the group. Days are separated by a date, and a red rule marks the first message you have not read. Scroll to the top of a conversation to load older messages. ### Copy or edit a message Hover over a message to see the available actions. **Copy message** puts the message text on the clipboard. **Edit message** appears on your own messages. It opens the text in an editable box, where **Enter** saves your change and **Esc** cancels it. Everyone then sees the message marked as **Edited**. System messages, such as the note recording a rename, can't be edited, and no message can be deleted. ### While someone is writing A line below the last message names the people currently typing and stacks their pictures. Beyond three people it counts them instead. ## Manage a group conversation The group header shows the conversation name and how many members are online. Select **Manage members** (the **...** button) to open the group menu. **Rename conversation** asks for the new name, which is required. The conversation is renamed for everyone and the change is recorded as a message in the thread. **Add member** opens the list of people you can add. The people you add are announced in the conversation. **Leave** records that you left and takes the conversation off your list. To remove someone, use the remove action next to their name in the member list below the menu. Confirm the removal, and that person will no longer receive the conversation's messages. You can remove a member only while the group has more than two people. ## Notifications With the chat panel closed, an incoming message arrives as a toast in the corner of the application. Select the toast to open that conversation. While the browser tab sits in the background, the message is also raised as a desktop notification. A direct message shows the sender's name. A group message shows the conversation name, with the sender's name in the message text. Desktop notifications require **Enable browser notifications** under **Notifications** in your configuration, and the browser's own permission, which is requested the first time you open chat or notifications after enabling the setting. They are available in the Modern Layout. The in-app toast is what the other layouts use. ## Rules and behaviour - The **Users** tab never lists you, inactive users, or system administrators. - Search in **Conversations** matches conversation names. It does not search message text. - Chat only sends text messages. You can't attach files. - If you use Chat in more than one browser tab or on more than one device at once, your conversations stay in sync across all of them. ## Configuration Chat is activated for your tenant by the Skills Workflow support team. Access is granted per user through the chat roles. **ChatNavigate** is the role that puts the icon in the top menu. Who each person can message is controlled by **Chat Visibility Restriction Enabled**, on the **Security** tab of the Configuration workspace: - With the setting off, everyone sees every active user except system administrators. - With the setting on, a user who has people on their chat visibility list sees only those people, together with anyone who put that user on their own list. A user whose list is empty keeps seeing everyone. These lists can't be edited from the WebApp. Ask the Skills Workflow support team to set them up. ## Related articles - [Using the Feed](/docs/product/files-and-collaboration/using-feed) - [Roles and Profiles](/docs/administration/system-roles-profiles) - [Notification Types](/docs/product/notifications/notification-types) --- ## Client Staff Plan Summary Workspace URL: https://documentation.skillsworkflow.com/docs/product/dashboards-and-reporting/client-staff-plan-summary Summary: Workspace provides a summary report of all fees and estimates under a company, client group and period selected. The Client Staff Plan Summary Workspace provides a summary report of all fees and estimates under a company, client group and period selected. This can be accessed by selecting “Client Staff Plan Summary” under “Workspaces” menu. The workspace has 2 sections: Company and Client Group – This is where you set the criteria to determine the fees and estimates to be included in the report by selecting from the dropdown, values for the following: - Company - Client Group - Start Date - End Date Deliverables Staffing – A customizable report that shows the staffing plan per estimate selected. The top section contains the unselected fields for the report. The user can customize his own report by dragging and dropping the columns “to and from” the unselected section and report section. Sort and Filter functions are available in each field column. In the default report format above the following fields are shown: - Client – Client where the Fee was created - Stage – Current stage of the Estimate - Version – Version number of the Estimate - Division – Division name where the typology group or user in the staff plan belong - Department – Department name where the typology group or user in the staff plan belong - Typology Group – Position included in the staff plan of the estimate - Name – User Name in instances where staff plan is created per user - Deliverable – Deliverables defined per estimate - Hours – Contracted hours for the typology group or user for the deliverable - TableRate – Hourly rate for the typology group or user defined in the rate card attached to the fee proposal. Only users with access to the rate card can see values in this field. ## Related articles - [Fees](/docs/product/commercial/fees) - [Create Estimate](/docs/product/commercial/estimates/create-estimate) --- ## Client Workspace URL: https://documentation.skillsworkflow.com/docs/product/dashboards-and-reporting/client-dashboards Summary: Workspaces are a powerful feature used to quickly support decisions related to a specific client or project. Workspaces are a powerful feature used to quickly support decisions related to a specific client or project. The goal is to give the ability to control processes in a very friendly and comprehensive way. As a project manager is very useful to understand the status of a specific client and control the profitability of each project. This way the PM will have the tools to negotiate with their clients. There are several Workspaces at the client level available in the system that will display different information. ### Burn Workspace 1. Go to the client module. 2. Select the client you want to check. 3. Press on Burn Workspace. You will find out a summary with total indicators: Planned, actual, revenue and cost Select the project you wish to analyze The system will display several graphics with detailed information related to the selected project You will be able to check total values for that specific project such as contracted hours, planned hours, actual hours, planned revenue, and actual cost. Also, you will be able to find the burn percentage (planned - actual hours) Project Time Burn This representation will show you a monthly distribution of planned versus actual hours. You will find out the same representation of the accumulated values as well. Project Revenue Burn This representation will show you a monthly distribution of planned revenue versus actual cost (based on user cost*actual hours). You will also find out the same representation of the corresponding accumulated values ### Profitability Workspace 1. Go to the client module; 2. Select the client you want to check; 3. Press on Profitability Workspace 4. This Workspace shows you in a glimpse the projects, under the client you have selected, which returns you a higher profit (based on the income value quoted to the client) You will be able to analyze the planned profit per project, and per typology. Additionally, you will be able to check the profit margin per project by percentage and value, and the profit per project (based on planned hours income, and actual hours cost) with the Pareto representation ### Project Allocation Workspace 1. Go to the client module; 2. Select the client you want to check; 3. Press on Project Allocation Workspace 4. Project Allocation Workspace will show you a table where you can check the following information per project: Users Capacity; - Actual hours already registered in the system; - Billable hours registered; - Allocation % Please note that this workspace is a table and allows you to add more fields if needed. To do so you should press on the icon at your right (marked in orange), and the system will show a field chooser as an Excel pivot table. Please note that you can either export to excel or print out this workspace by pressing outside the grid with the right function of your mouse. ## Related articles - [Create a commercial client](/docs/product/commercial/crm/create-commercial-client) - [Create a Project](/docs/product/projects-and-jobs/create-projects) --- ## Commercial URL: https://documentation.skillsworkflow.com/docs/product/commercial Summary: The commercial side: CRM, rate cards, estimates and fees. # Commercial What gets sold, and at what price. The CRM holds commercial clients, their contacts and products, and the leads and activities against them. Rate cards set the prices. Estimates quote work to a client; a fee is the agreement those estimates and projects are created under. --- ## Create a client contact URL: https://documentation.skillsworkflow.com/docs/product/commercial/crm/client-contacts Summary: In order to create a new client contact with all the client details, you should access the “CLIENTS” module and go into the “Client Contact” tab. In order to create a new client contact with all the client details, you should access the "CLIENTS" module and go into the "Client Contact" tab. Select the client you wish to add the contact to. To create a new client contact, you should follow the steps below: 1. Access the "Clients" module and double-click to open a specific client page. 2. Click on the "Client Contact" tab followed by the "+" button to create a new line. 3. To save these changes, it is necessary to fill in the "Name" field. 4. Save all the changes made by clicking on the dis symbol. > To remove a line/client contact, you will only need to click on the "x" button. Once created, the client contact can also be associated with another client. How to associate an existing client contact with another client. Select the client you wish to associate a contact with. When clicking on the "link" option, the system will show a pop-up box with all the available contacts. You will only have to select the client contact needed and click on the "Save" option. When clicking on the "Save" option, the contact will be automatically available on the client details. It won't be necessary to save the changes made, as the system will automatically do it for you. ## Related articles - [Create a commercial client](/docs/product/commercial/crm/create-commercial-client) - [Create lead](/docs/product/commercial/crm/create-lead) --- ## Create a commercial client URL: https://documentation.skillsworkflow.com/docs/product/commercial/crm/commercial-clients Summary: To create a new commercial client you must go to the “Maintenance” module and to the sub-list “Clients”. To create a new commercial client you must go to the "Maintenance" module and to the sub-list "Clients". - Click on the option "+ New Commercial Client". Verify that this option will lead you to the Client creation screen. - Ensure you fill in the following fields: Name - client's name Code - client's code (may be used for the project/job code depending on configuration) External ID - client ID from the ERP (if applicable) Client Manager - user responsible for this client Timesheet Approver Type - choose who should approve time for this client (user responsible, project owner, or client manager) Timesheet Level - choose the highest level at which users can enter time for this client (Client, Product, Project, Job) >After saving the Client, several tabs will appear automatically at the bottom of the page, where you can add new products and associate users. Once all fields are complete, you will be able to create Projects and Jobs for this client. ## Related articles - [Create a client contact](/docs/product/commercial/crm/create-client-contact) - [Create a commercial product](/docs/product/commercial/crm/create-commercial-product) - [Create lead](/docs/product/commercial/crm/create-lead) --- ## Create a commercial product URL: https://documentation.skillsworkflow.com/docs/product/commercial/crm/commercial-products Summary: To create a new commercial product you must go to the “Maintenance” module and to the sub-list “Clients”. To create a new commercial product you must go to the "Maintenance" module and to the sub-list "Clients". Select the commercial client which you need to create the product under. To create a new product, you will have to: - Go to the tab products at the bottom; - Press on "+" button - Type the product's name, and check the box "Active" - Save the changes by clicking on the disk symbol. > Associating product to a specific company > This is only applicable if within the same client, certain products are only available for one company and not the other(s). > Once all the information is complete click on the top of the product to go to the product's page. - On the tab, CommercialProductCompanies click on the "+" to add the company that will work with this specific product. - Choose the company from the dropdown and then save by clicking on the disk symbol. - If you have billing products you will also be able to associate them with your commercial products. ## Related articles - [Create a commercial client](/docs/product/commercial/crm/create-commercial-client) --- ## Create a Project URL: https://documentation.skillsworkflow.com/docs/product/projects-and-jobs/create-a-project Summary: To create a new Project, navigate to the “Clients” module. ### A Project is an umbrella that groups a bundle of related jobs inside. 1. To create a new Project, navigate to the "Clients" module. 2. Verify that you can navigate by clicking on Clients in the side bar. 3. After selecting a client click on the "+" to open a new Project creation popup. 4. Fill in the yellow (mandatory) fields. - **Title** - Name you would like to give to the Project. - **Begin/End** - Choose when the Project starts and when it will end. - **Type** - Choose from a drop-down list. E.g. New Business, Admin, etc. - **Product** - Product you are creating this Project for. Select from a dropdown list of Products you have access to. ### Add a Brief to the Project 1. You can add a brief with all the information and customer instructions. 2. Just type in all the information on the description, inside the new Project creation popup. ### Attach a file 1. You can also attach files to the Project simply by dragging them inside the popup, or by clicking on the dotted square. 2. This is useful for adding brief documents or presentations, in any of the main formats (Word, PPT, Excel, PDF, etc.) ### After filling in all the fields, you will need to activate the project. 1. Click on the check to close the form and select the small blue arrow on the bottom right. 2. After clicking on it, the Project will get a number (see Project code at the top) and it will no longer be on the stage Draft. ### Add people to the Project's team 1. If you have access to change the Team you will see an Add Assignment symbol bellow the Brief section. 2. Add or remove people to each of the groups by clicking on the pencil. 3. A dropdown will appear with a list of users. 4. Select the users that you want to assign and click on the check to add them to the Team. ### At the top of the page you will be able to find various tabs with information about this Project - **Feed** - Activity and comments related with the Project. - **Jobs** - List of existing jobs belonging to this Project. - **Planned Time** - Planned versus Actual hours per typology and/or user for the Project. - **Files** - All the files uploaded into this Project will appear on this tab. - **History** - Track of status changes. You can see for example who created the Project and at what time. - **Others** - You may also find other tabs depending on the modules of the system you have access to. ## Related articles - [Create Jobs](/docs/product/projects-and-jobs/create-jobs) - [Gantt](/docs/product/planning-and-scheduling/gantt) - [Planned Time](/docs/product/planning-and-scheduling/resourcing/planned-hours) - [Fees](/docs/product/commercial/fees) --- ## Create an activity URL: https://documentation.skillsworkflow.com/docs/product/commercial/crm/activities Summary: To create a new Activity, navigate to the Lead. 1. To create a new Activity, navigate to the Lead. 2. Select the active Lead under which you want to include the new Activity under, and click the "+" at the top right corner. 3. Fill in the Activity creation popup form. - **Title** - Name you would like to give to the Activity. - **Type** - Type of activity you want to create (e.g. Email, Call, Meeting, etc.) - **Start/End** - Choose when the Job starts and when it will end. 4. Once you complete all the fields click on the check mark icon. ### Add a description and files 1. Just type in all the information on the description inside the creation popup. 2. At any time you can change the Description. For that, you just need to click on the option that says "Edit". 3. You can also attach files such as images, and emails, by dragging or clicking on the dotted square. 4. Save it, close the Activity form by clicking on the check, and then on the bottom right side of the popup click on the small blue arrow. 5. A pop-up will appear saying your Activity was successfully created. Click on this message to navigate directly to the Activity. ### Move the Activity status 1. Once you create the Activity you will need to continue to move the Activity Forward by changing the Activity Status. 2. For that, you just need to click on the symbol and select one of the available options. ### Add people to the Team 1. If you have access to change the Team you will see an Add Assignment symbol below the description section. 2. Add or remove people to each of the groups by clicking on the pencil. 3. A dropdown will appear with a list of users. 4. Select the users that you want and click on the check to add them to the Team. ### Add a new file to the Activity 1. To add a new file to the Activity you just need to click on the symbol and submit the post. 2. The file will appear automatically on the Activity feed, where you can easily download it. 3. You can also check all Activity related files on the tab "Files". In order to notify someone on your team about a new post or Activity related topic, you can always use the "Notifications" option. ### Notificatify people 1. For that click on the symbol and select the users you want to notify. 2. The user will be tagged on this comment and a notification will be sent. ### Document tabs At the top of the page, you will be able to find various tabs with information about this Activity - **Feed** - Activity and comments related to the Activity. - **Files** - All the files uploaded into this Activity will appear on this tab. - **History** - Track of status changes. You can see for example who created the Activity and at what time. - **Others** - You may also find other tabs depending on the modules of the system you have access to. ## Related articles - [Create lead](/docs/product/commercial/crm/create-lead) --- ## Create Client Requests URL: https://documentation.skillsworkflow.com/docs/product/briefing-and-requests/client-requests Summary: From the client perspective, you can now create and control your own requests using Skills Workflow. From the client perspective, you can now create and control your own requests using Skills Workflow. ### After collecting your credentials and logging in, the first step is to create your request. 1. For that you just need to access the Project you're involved with, create a new Job. 2. You are only going to have access to the Projects you're involved with. ### Filling in the job creation popup form. - **Title** - name you would like to give to the Job. - **Department** - Department to which the request/Job belongs to. - **Job Type** - Type of Job you want to create (e.g. TVC, Print, etc). - **Begin/End** - Choose when the Job starts and when it will end. ### After completing all the details, make sure you submit the post in order to create the Job. - Once the Job is created, it will get a number that can be used as a reference. - Don't forget to upload all the relevant information such as files, briefs, etc in order for the Account to be able to fully understand your request. - Each Job you create represents a new request for the Agency. You can create as many jobs/requests as you need. ### Move the Job status 1. Once you activate the Job you will need to continue to move the Job Forward by changing the Job Status. 2. For that you just need to click on the Screen_Shot_2017-10-10_at_12.21.36.png symbol and select one of the available options. 3. Once you send the Job, the Agency will be able to review the request and Assign the team. 4. Please note that all approvals and adjustments should be registered under the same Job/Request. This way it would be easy to track all changes needed, and the history of each request. ### Throughout the process, you can always check the stage of your requests by clicking on the Job sub-list "Mine". 1. By clicking on this sub-list you can check in which stage the Job is and also access the details of the Job, such as new posts, comments, etc. 2. Once your Request is complete, you will be notified that the Job is completed. Also it is possible to create Sub-Jobs under a main Job. ### Create Sub-Jobs under a main Job 1. By clicking on the main job you can create sub-jobs with specific requests related with the main one. 2. Inside the Job press on the option "+", create sub-job. 3. The information needed is the same you need to fill in on a Job. ## Related articles - [Create a Project](/docs/product/projects-and-jobs/create-projects) - [Create a commercial client](/docs/product/commercial/crm/create-commercial-client) --- ## Create estimate URL: https://documentation.skillsworkflow.com/docs/product/commercial/crm/estimates-from-crm Summary: Estimates can either be linked to Fees or created directly under a Company, Leads, or Activity. Estimates can either be linked to Fees or created directly under a Company, Leads, or Activity. Should you wish to create an estimate associated with a specific Fee, please check our lesson 3 under the contracts section. To generate an estimate under a Company or Activity you should navigate onto the document you wish to generate the estimate, press on the option +, and choose "estimate" Fill in the following fields: - **Department** - The system will suggest the user department by default, but you can select other planable departments and set up different workflows if needed. - **Estimate Type** - You can have several estimate types which will allow different configurations such as workflows, pull-out reports, etc. - Click on the check mark to submit the post. The system will show a popup message with the confirmation that the estimate was successfully created. On the Info tab, you can fill in the following fields: - **Payment Condition** - It can be inherited from the Client or manually chosen. - **Currency** - It can be inherited from the default currency defined in the Company or manually chosen. - **Rate Card** and **Rate Card Column** - It can be inherited from the Client or manually picked. - **Overheads** and **Margins** - Defined manually for each Estimate (optional). ## Create Quotes To start building your Estimate details navigate to the Quotes tab where you will find 4 different sections: - **Deliverables** - these are the services sold to the client (each line can represent actual deliverables, i.e. projects/jobs; a monthly fee, or any other structure you want to use for breaking down your Estimate). - **Third Party Costs** - this is the first component of the estimate. These relate to external suppliers. - **Expenses** - this is the second component of the estimate. Transportation, meals, hotel, are just some examples of expenses that can be estimated here. - **Resources** - this is the final component of the estimate. Represents internal resources/man-hours being scoped for. To create new Quotes you should: 1. Press on "+" to create a deliverable to estimate. 2. Each deliverable can represent a month in the retainer fee; a service, etc. 3. For each Deliverable you should include: - **Description** - Fill in a name that describes what you are selling to the Client. - **Service** - Choose the type of service you are Quoting. - **Tax**- Can come directly from the Client or be manually entered. ### Quoting Third Party To start quoting the Third Party, click on the word Third Party and the section will open up. 1. Select the deliverable you want to quote for from the dropdown. 2. Press on "+" to add Estimate Details. 3. The description, and service will be inhered from the deliverable line. 4. Select the supplier (external costs), supplier payment conditions. 5. Unit cost, and quantity cost (#). 6. Fill in the % Fee, or value to get your sell value. 7. Click on the Save icon. 8. Repeat the process if you need to add several external costs. Please note that you can have several external costs under one client line. It will depend on how you want to show the estimate details to clients. ### Quoting Expenses To start quoting expenses, click on the "Expense" word and the section will open up. 1. Select the deliverable you want to quote for from the dropdown. 2. Press on "+" to add Estimate Details. 3. Select the expense type you need to quote (eg. Meals, Hotel). 4. Fill in the unit cost and quantity #. 5. Click on the Save icon. 6. Repeat the process if you need to add several expenses. ### Quoting Resources To start quoting the resources, click on the "Resources" word and the section will open up. 1. Select the deliverable you want to quote for from the dropdown. 2. Press on "+" to add Estimate Details or add multiple Typologies at once by clicking on the button Typologies icon. 3. You can scope based on typologies (i.e. titles) and/or specific Users. For each Typology you will have to fill in the following required fields: - **Table Rate** - Inherited automatically from the Table Rate chosen before on the Info tab. - **Unit Cost** - Automatically the same as the table rate, but could be manually changed. Used only if you want to use a different rate that the one from the chosen Rate Card (table rate). - **Hours** - Number of hours being sold to the Client. - **Total Cost** - Hours x Unit Cost. - **Unit Income** - Unit Cost + Margin. - **Total Sell** - Total Cost + Margin or Unit Income x Hours. * The Margin is the one defined on the Estimate's Info tab. As you fill in the values, the total per Deliverable on the Deliverables section at the top will be automatically updated. Note that each individual column on the Estimate is controlled by access roles. Please note that you can have several external costs, expenses, and resources under one client line. It will depend on how you want to show the estimate details to clients ## Related articles - [Create Estimate](/docs/product/commercial/estimates/create-estimate) - [Create lead](/docs/product/commercial/crm/create-lead) --- ## Create Estimate URL: https://documentation.skillsworkflow.com/docs/product/commercial/estimates/create-an-estimate Summary: Estimates can either be linked to Fees or created directly under a Project or Job. Estimates can either be linked to Fees or created directly under a Project or Job. Should you wish to create an estimate associated to a specific Fee, please check our lesson 3 under contracts section. To generate a estimate under a Project or Job you should navigate onto the document you wish to generate the estimate, press on the option + and choose "estimate" Fill in the following fields: - **Department** - The system will suggest the user department by default, but you can select other planable departments and set up different workflows if needed. - **Estimate Type** - You can have several estimate types which will allow different configurations such as workflows, pull out reports, etc. - Hit ok and submit the post. The system will show a popup message with the confirmation that the estimate was successfully created. On the Info tab you can fill in the following fields: - **Payment Condition** - It can be inherited from the Client or manually chosen. - **Currency** - It can be inherited from the default currency defined in the Company or manually chosen. - **Rate Card** and **Rate Card Column** - It can be inherited from the Client or manually picked. - **Overheads** and **Margins** - Defined manually for each Estimate (optional). To start building your Estimate details navigate on the Quotes tab where you will find 4 different sections: - **Deliverables** - these are the services sold to the client (each line can represent actual deliverables, i.e. projects/jobs; a monthly fee, or any other structure you want to use for breaking down your Estimate. - **Third Party Costs** - this is the first component of the estimate. These relate to external suppliers. - **Expenses** - this is the second component of the estimate. Transportation, meals, hotel, are just some examples of expenses that can be estimated here. - **Resources** - this is the final component of the estimate. Represents internal resources/man-hours being scoped for. To create new Quotes you should: 1. Press on "+" to create a deliverable to estimate. 2. Each deliverable can represent a month in the retainer fee; a service, etc. 3. For each Deliverable you should include: - **Description** - Fill in a name that describes what you are selling to the Client. - **Service** - Choose the type of service you are Quoting. - **Tax**- Can come directly from the Client or be manually entered. To start quoting the Third Party, click on the word Third Party and the section will open up. 1. Select the deliverable you want to quote for from the dropdown. 2. Press on "+" to add Estimate Details. 3. The description, and service will be inhered from the deliverable line. 4. Select the supplier (external costs), supplier payment conditions. 5. Unit cost, and quantity cost (#). 6. Fill in the % Fee, or value to get your sell value. 7. Hit save. 8. Repeat the process if you need to add several external costs. Please note that you can have several external cost under one client line. It will depend how you want to show the estimate details to clients. 1. Select the deliverable you want to quote for from the dropdown. 2. Press on "+" to add Estimate Details. 3. Select the expense type you need to quote (eg. Meals, Hotel). 4. Fill in the unit cost, and quantity #. 5. Hit save. 6. Repeat the process if you need to add several expenses. To start quoting the resources, click on the "Resources" word and the section will open up. 1. Select the deliverable you want to quote for from the dropdown. 2. Press on "+" to add Estimate Details or add multiple Typologies at once by clicking on the button Typologies icon. 3. You can scope based on typologies (i.e. titles) and/or specific Users. For each Typology you will have to fill in the following required fields: - **Table Rate** - Inherited automatically from the Table Rate chosen before on the Info tab. - **Unit Cost** - Automatically the same as the table rate, but could be manually changed. Used only if you want to use a different rate that the one from the chosen Rate Card (table rate). - **Hours** - Number of hours being sold to the Client. - **Total Cost** - Hours x Unit Cost. - **Unit Income** - Unit Cost + Margin. - **Total Sell** - Total Cost + Margin or Unit Income x Hours. The Margin is the one defined on the Estimate's Info tab. As you fill in the values, the total per Deliverable on the Deliverables section at the top will be automatically updated. Note that each individual column on the Estimate is controlled by access roles. Please note that you can have several external costs, expenses and resources under one client line. It will depend how you want to show the estimate details to clients ## Related articles - [Create Rate Cards](/docs/product/commercial/rates/rate-cards) - [Fees](/docs/product/commercial/fees) - [Invoice an Estimate](/docs/product/commercial/estimates/invoice-estimate) --- ## Create Expenses URL: https://documentation.skillsworkflow.com/docs/product/billing-and-costs/expenses/create-expenses Summary: To create expenses navigate to Project module and select a project to add receipts. ### Expenses can be created in two ways: - Directly on a Project - On an Expense Sheet ### Create directly on the Project To create expenses navigate to Project module and select a project to add receipts. 1. Click on the icon '+' to create a new Expense Item. 2. Add a description 3. Add a file 4. Fill the remaining fields 5. Click 'ok' and submit post. 6. Repeat the process if there are more expense to add to the same project. ### Create on Expense Sheet 1. Go the Expense Sheets module. 2. Select All list. 3. Select a Expense Sheet where you intend to add an Expense and click on the '+' to create. 4. Fill the fields, click 'ok' and submit the post. 5. Add a description. 6. Select the type of Expense. 7. Add an image with the recit to add a file. 8. In the field Document search for the project or client you want to link. 9. Add expense's value. 10. Click 'ok'. 11. Repeat the process if there's more than 1 expense. Please, take into account that all fields in yellow are mandatory. Inside the same expense sheet different project's receipts can be added. 1. Select the expense you which to copy and click on duplicate. 2. The system will generate an automatic number and also a confirmation pop-up. 3. Go to the expense sheet, in the Feed exchange the stage in order to send for the responsible for approval. ## Related articles - [Expense Sheets](/docs/product/billing-and-costs/expenses/expense-sheets) - [Approve Expenses](/docs/product/billing-and-costs/expenses/approve-expenses) --- ## Create Jobs URL: https://documentation.skillsworkflow.com/docs/product/projects-and-jobs/create-jobs Summary: To create a new Job, navigate to the “Projects” module. 1. To create a new Job, navigate to the "Projects" module. 2. Select the active Project where you want to include the new Job under, and click the "+" at the top right corner. 3. If you want to create a Job inside a Job, you can go to tab Jobs inside the Project's page, select a Job and click on the option "+". 4. Fill in the Job creation popup form. - **Title** - Name you would like to give to the Job. - **Department** - Department/Cost Center to which the job belongs to. - **Job Type** - Type of job you want to create (e.g. TVC, Print, etc.) - **Start/ End** - Choose when the Job starts and when it will end. 5. Once you complete all the fields click on the option 'check'. ### Add Brief and upload files 1. Just type in all the information on the description inside the new Job creation popup. 2. At any time you can change the Brief. For that you just need to click on the option that says "Edit". 3. You can also attach files such as briefs, images, emails, by dragging or clicking on the dotted square. After filling in all the information, you will need to activate the Job ### Activate the job 1. To activate it and generate a job number, close the Job form by clicking on the check, and then on the bottom right side of the popup click on the small blue arrow. 2. A pop-up will appear saying your Job was successfully created. Click on this message to navigate directly to the Job. ### Move the Job status 1. Once you activate the Job you will need to continue to move the Job Forward by changing the Job Status. 2. For that you just need to click on the symbol and select one of the available options. ### Add people to the Job's Team 1. If you have access to change the Team you will see an Add Assignment symbol bellow the brief section. 2. Add or remove people to each of the groups by clicking on the pencil. 3. A dropdown will appear with a list of users. 4. Select the users that you want and click on the check to add them to the Team. ### Add a new file to the Job 1. To add a new file to the Job you just need to click on the symbol and submit the post. 2. The file will appear automatically on the Job feed, where you can easily download it. 3. You can also check all Job related files on the tab "Files". In order to notify someone on your team about a new post or Job related topics, you can always use the "Notifications" option. ### Notifications 1. For that click on the symbol and select the users you want to notify. 2. The user will be tagged on this comment and a notification will be sent. ### At the top of the page you will be able to find various tabs with information about this Job. - **Feed** - Activity and comments related with the Job. - **Jobs** - List of existing jobs belonging to this Job. - **Files** - All the files uploaded into this Project will appear on this tab. - **History** - Track of status changes. You can see for example who created the Project and at what time. - **Additional Information** - All the non-standard Job's fields. - **Others** - You may also find other tabs depending on the modules of the system you have access to. ## Related articles - [Create a Project](/docs/product/projects-and-jobs/create-projects) - [Gantt](/docs/product/planning-and-scheduling/gantt) - [What is a Team and what does each Group represent?](/docs/product/people/teams/what-is-a-team) - [Manage List View](/docs/product/projects-and-jobs/list-view) --- ## Create lead URL: https://documentation.skillsworkflow.com/docs/product/commercial/crm/leads Summary: To create a new Lead, navigate to the “Clients” module. A Lead is an umbrella that groups a bundle of related activities and deals. 2. After selecting a client click on the "+" to open a new Lead creation popup. 3. Fill in the yellow (mandatory) fields. - **Name** - Name you would like to give to the Lead. - **Type** - Choose from a drop-down list. E.g. Partnership, Direct Sales, etc. - **Lead Owner** - The owner of the Lead. - **Domain** - The website domain of the Lead. ### Add a description and files 1. You can add a description with all the information and instructions. 2. Just type in all the information on the description field, inside the creation popup. 3. You can also attach files by dragging them inside the popup, or by clicking on the dotted square. 4. This is useful for adding documents or presentations, in any of the main formats (Word, PPT, Excel, PDF, etc.) ### Add people to the team 1. If you have access to change the Team you will see an Add Assignment symbol below the Description section. 2. Add or remove people to each of the groups by clicking on the pencil. 3. A dropdown will appear with a list of users. 4. Select the users that you want to assign and click on the check to add them to the Team. ### Document tabs At the top of the page, you will be able to find various tabs with information about this Lead: - **Feed** - All the stages and comments related to the Lead. - **Activities** - List of existing activities belonging to this Lead. - **Files** - All the files uploaded to this Lead will appear on this tab. - **History** - Track of status changes. You can see for example who created the Lead and at what time. - **Others** - You may also find other tabs depending on the modules of the system you have access to. ## Related articles - [Create an activity](/docs/product/commercial/crm/create-activity) - [Create a commercial client](/docs/product/commercial/crm/create-commercial-client) - [Create estimate](/docs/product/commercial/crm/create-estimate) --- ## Create Rate Cards URL: https://documentation.skillsworkflow.com/docs/product/commercial/rates/rate-cards Summary: Rate Cards are prices/costs for typology groups and/or users. Rate Cards are prices/costs for typology groups and/or users. You can set multiple Rate Cards and Rate Cards columns in the same table. ## Rate Cards can be managed in two ways: ### Sales values - Add rates based on the sales values for a specific client(including margin and fixed costs). - In this case, the bill's team does not need to include margin and fixed costs when creating rates. - Some clients have a unique sales rate, which ensures that the bill's team doesn 't send different prices/costs to the same cliente. ### Costs values - Add rates based on the costs values for a user/typology group. - In this case, bill's team will have to manage margin and fixed costs for the client. ### Create Rate Tables 1. Go to the Maintenance and enter the Rate Cards workspace. 2. Click on the '+' icon. 3. Fill atleast the required fields - Name - Add a description. - Number - Add an internal number manually. - Company - Select a company on which the rate will be applied. - Start Date / End Date - Choose a start and end date for the new rate. Rate Cards can be edited on the Rate Cards on Maintanance or in workspace All on Rate Cards module in the Menu. - Add a line to add a specific typology. - Select a typology group. - Select a specific user (if you want to add this detail). - Add the rate for the selected typology / user. - In this example, in the same rate table, there are 3 prices / costs available (standard, Discount 10% and Discount 30%). - Click on the top of each column to add values. - Click on record on the floppy disk symbol. If you want to add several users or groups of typology at the same time: - Click to add groups of typology or users. - In the pop-up, select several groups of typology or users and add them simultaneouslyc click "ok". - Add values ​​to rows and columns by clicking on the top of each cell. ## Related articles - [Create Estimate](/docs/product/commercial/estimates/create-estimate) - [Fees](/docs/product/commercial/fees) --- ## Credit Notes URL: https://documentation.skillsworkflow.com/docs/product/billing-and-costs/billing/credit-notes Summary: Whenever you change the sales values ​​of the invoiced budget, to a lower value the system will suggest that a credit note be issued. Whenever you change the sales values ​​of the invoiced budget, to a lower value the system will suggest that a credit note be issued. Requests for the issuance of credit notes to customers in the system, and in this way inform the financial team to proceed with the creation / synchronization of the document to the external financial system, and generate the final credit. ### Total credit - To issue a credit request, within the budget approved by the customer, you must navigate to the line / s that you want to credit to the customer. - To generate a credit for the total value of the invoices that you have previously issued, in the budget lines you must put the values, or quantity to 0. - Navigate to the Feed and instruct the system to bill again. Don't forget to validate the billing conditions, as already described in Lesson 1. - The system will issue a credit note document for the total amount that will be processed by the finance department. ### Partial credit - You can issue partial credits from customer lines, that is, initially invoiced a value, and you need to issue a credit from a party. - To do this, just go to the line you want to credit and adjust the sale value of it. - In other words, in the example below, the line was billed for 104,100 and we intend to issue a credit in the amount of 50,600. Therefore, we would have to go to the line and adjust the sale price to 53,500. - When finished, you should go to the feed again and give instructions to the system to invoice / credit. - Don't forget to define the billing conditions described in Lesson 1. You can navigate to the customer credit notes area, and you can find the document you have just issued For the issuance of credit, the invoices in the budget must be in an "integrated" stage - After the creation of credit applications, due to legal obligations, you will have to identify the reason in the lines, only in this way can it be integrated into the external system. - To validate the information, and to print, you must navigate to the purchase order document by clicking on the line you want to validate. - The system will show the details of the document, values, contracted service, etc. - To print just click on the pdf option in the upper right corner, and a PDF document will be generated that you can download and send by email to the respective supplier You can also consult the list of all your purchase orders by browsing the modules in the browser on your left. In the list of purchase orders you can apply several filters, such as: client, project, budget. ## Related articles - [Invoice Authorizations](/docs/product/billing-and-costs/billing/invoice-authorizations) - [Invoice an Estimate](/docs/product/commercial/estimates/invoice-estimate) --- ## Environment Workspace URL: https://documentation.skillsworkflow.com/docs/product/dashboards-and-reporting/environment-workspace Summary: It is now possible to change the appearance of Skills Workflow. It is now possible to change the appearance of Skills Workflow. Make it look like your agency, differentiate it from the others and show your brand identity to all your team and clients. This can be done through the Environment Workspace. In order to access it, Users must have the following profiles linked to their profile: - MaintenanceNavigate - MaintenanceSave - EnvironmentNavigate - EnvironmentSave To access the Environment Workspace, log in to Skills Workflow, click on your username in the top right corner of the home page, select the "Maintenance" option and press the "Ambient" module. There are 3 sections in the Workspace where the following are defined: 1. Images: images to use as background and company logos. 2. Translations: terms within the system that can be renamed as needed. 3. Colors: Colors to be used for the background, icons, bars, and fonts. - Background Image URL – Enter here the URL of the image you want to use as the background for the login page. Select images that can relate to your agency. Avoid images with lots of objects/noise. Prioritize images with depth of field. - Background Image Style – Enter the style properties to apply to the image. - Company Logo URL – Select a logo that is common to all companies within the instance, preferably with a transparent background. - Company Logo Style – Enter the style properties to set the size of the company logo. Home tab - Top Bar Image URL – Logo you want to place at the top of the vertical menu bar on the left of the home page. The same logo as the login page can be applied. The logo must not exceed the limits of the bar and must be aligned with the breadcrumbs and menu items. - Top Bar Image Style – Enter the style properties to set the size of the top bar image Translations - Press the + sign to add a new row - Select the original term and write the new one that you want to see in the system Colors - Login Tab – Define the colors for the different components found in the login box on the login page. - Top Bar Tab – Define the colors for the different components found on the top horizontal bar of the home page. - Sidebar tab: defines the colors of the different components found in the left vertical bar of the home page where the system menu is displayed. To configure the colors, simply type in your color code or click the dropdown menu and the color guide will be displayed. When selecting colors, make sure there is enough contrast between the background and the fonts/icons. Hover State should be more visually appealing than normal state Once you have configured the images and colors, click the Save button to save your changes. ## Related articles - [Client Workspace](/docs/product/dashboards-and-reporting/client-dashboard) --- ## Expense Sheets URL: https://documentation.skillsworkflow.com/docs/product/billing-and-costs/expenses/expense-sheets Summary: It's possible to create and manage expenses relative to projects and other activities. It's possible to create and manage expenses relative to projects and other activities. All costs will afect the project's profitability, for that reason To create a new **Expense Sheet** (multi-expense aggregating sheet), take the following steps. 2. Select All list. 3. Click on the '+' on the expenses list. 4. Fill the Expense's fields: - **Title** - A name which helps to easly find a specific expense. - **Department** - The department to which the user belongs to. - **Type** - Select the type of expense (this information is very important, it will define the flow of the expense). - **Start Date / End Date** - Select the start date of the expense and the end date (should reflect the date on which the employee is reimbursed). ## Related articles - [Create Expenses](/docs/product/billing-and-costs/expenses/create-expenses) - [Approve Expenses](/docs/product/billing-and-costs/expenses/approve-expenses) --- ## Favorites URL: https://documentation.skillsworkflow.com/docs/product/favorites Summary: Favorites let you bookmark the documents and dashboards you access most often. Favorites let you bookmark the documents and dashboards you access most often. Favorited items appear in the **search popup** and optionally in the **side menu**, giving you quick access without navigating through modules. ## Adding a Document to Favorites There are several ways to mark a document as a favorite: ### From the Document Header 1. Open any document (Project, Job, Deliverable, etc.). 2. Right-click the document header area. 3. Select **Add as Favorite** from the context menu. ### From a Grid Row 1. In any list or grid view, look for the **bookmark icon** column on the left side of each row. 2. Hover over a row to reveal the bookmark icon. 3. Click the bookmark icon to toggle the favorite status. Alternatively, right-click any row and select **Add to Favorites** from the context menu. ### Visual Indicators - A **solid bookmark** icon (filled, in pink/red) means the document is favorited. - A **light bookmark** icon (outline) means it is not favorited. ## Removing a Favorite To remove a document from your favorites: - **From the document header** — right-click and select **Remove as Favorite**. - **From a grid row** — click the solid bookmark icon to unfavorite, or right-click and select **Remove from Favorites**. ## Accessing Your Favorites ### Search Popup 1. Press **`Ctrl+S`** (Windows/Linux) or **`⌘+S`** (Mac) to open the search popup. You can also click the search icon in the top menu bar. 2. In the popup, click the **Favorites** tab to see all your favorited documents. 1. Click on any item to navigate directly to that document. The search popup has three tabs: | Tab | Description | |---|---| | **Find** | Search across all documents | | **Mine** | Documents assigned to you | | **Favorites** | Your bookmarked documents | ### Side Menu When enabled, your favorites also appear as a dedicated section in the left side menu, providing one-click access to your most-used documents. The Favorites section in the side menu must be enabled by your administrator in **System Settings > Favorites > Enable Favorites in Menu**. ## What Can Be Favorited You can favorite any document type available in the system, including: - Projects - Jobs - Deliverables - Estimates - Bills - Contracts - Clients - Requests - Purchase Orders - Dashboards and Workspaces ## Tips - Use favorites to keep your most active projects and documents at your fingertips. - The **`Ctrl+S` / `⌘+S`** shortcut is the fastest way to reach your favorites. - Favorites are personal — only you can see your own favorites list. - Favorites are stored on the server, so they follow you across devices and browsers. --- ## Fee Workspace URL: https://documentation.skillsworkflow.com/docs/product/dashboards-and-reporting/contract-dashboards Summary: Workspaces are a powerful feature used to quickly support decisions related to a specific contract. Workspaces are a powerful feature used to quickly support decisions related to a specific contract. The goal is to give the user the ability to control processes in a very friendly and comprehensive way. As a project manager, it is very useful to understand the status of a specific client and control the profitability of each project and contract. This way the PM will have the necessary tools to negotiate with their clients. There are several workspaces at the Contract-level available in the system that will display different information. #### Burn Workspace 1. Select the contract you want to analyze. 2. Click on the "Burn Workspace" tab. 3. Select the project you want to check. You will find several representations that will show you in a glimpse whether your Contract is already burned. Also, there's a summary representation that will show you the total planned, contracted, cost and income. After selecting the project inside the contract you wish to analyze in detail, the system will give you the information of actual hours, actual cost, planned hours, planned income, contribution margin and contracted hours applied under that specific project. 4. Below you will find several pie representations related to the project you have selected. #### Typology group planned time This representation shows the number of planned hours per typology group. #### Typology group actual time This representation shows the number of actual hours per typology group. #### Typology group contracted time This representation shows the number of contracted hours per typology group, applied to the project previously selected. ### Resources Workspace 1. Inside the previously selected contract 2. Click on the "Resources Workspace" tab You will find out a summary with the overall status of your contract, in this example, we can observe that the actual time is almost burning out the contracted hours Additionally, you will be able to control which typology is filling in more actual hours. #### Typology group burn This representation will allow you to check if the planned hours or actual hours are burning the contracted hours you have previously sold to your client. #### User burn Also, you will be able to check which user is filling in more hours under your project/contract ### Staffing Workspace - Inside the previously selected contract - Click on the "Staffing Workspace" tab The first representation works as a pivot table and shows you the planned time per typology group per deliverable (meaning the services you have previously sold/quote to your client) It works as an Excel pivot table which allows you to re-organize your view if needed, adding information from the column chooser. By default, you will be able to check per deliverable the number of planned hours, the related rate and the utilization percentage of a specific typology group. #### Monthly distribution This representation allows you to control on a monthly basis the planned time VS the user's utilization and income. #### Typology Contribution Based on planned VS actual time this representation shows the contribution of each typology group for your contract Please note that you can print out or export any of the described workspaces ## Related articles - [Fees](/docs/product/commercial/fees) - [Create Estimate](/docs/product/commercial/estimates/create-estimate) --- ## Fees URL: https://documentation.skillsworkflow.com/docs/product/commercial/fees Summary: A Fee is the commercial agreement with a client for a number of hours or deliverables, tracked against a Price Table, that a client's Projects and Estimates are created under. # Fees In Skills Workflow this is called a Fee: the agreement with a client for a number of hours or deliverables, tracked against a Price Table. Many agencies would call the same record a contract — it registers the hours sold to a client, and tracks that number against the hours actually placed across the Projects created under it. A Fee is associated with a specific client, and must be associated with a Price Table. ## Working with a Fee A Fee's own fields are its Name, Owner, Start Date, End Date, and Stage. Its **Estimates** section holds the Estimates created against it, and its **Projects** section holds the Projects created against it — a Fee can create either directly. A Fee also has **Files**, **Feed**, **History** and **User Fields** sections, like other documents in Skills Workflow. A Fee, with its Feed, Info, Projects and Estimates tabs, and the option to create a Project or an Estimate directly from it. ## Availability Opening Fees needs the **ContractNavigate** permission; viewing a Fee needs **ContractRead**, creating one needs **ContractCreate**, and editing one needs **ContractWrite**. ## Related articles - [Create an Estimate](../estimates/create-an-estimate.md) - [Projects on a Fee](projects-on-a-fee.md) - [Rate Cards](../rates/rate-cards.md) --- ## Files URL: https://documentation.skillsworkflow.com/docs/product/files-and-collaboration/files Summary: The Files area is the document store: a file system of its own, reached from the main menu, separate from the files attached to an individual document. # Files Files is its own area in the main menu, backed by a file system of its own. It sits alongside — and is separate from — the **Files** tab that individual documents such as projects, jobs and bills carry. ## Availability Opening Files needs the **FilesNavigate** permission. Viewing needs **FilesRead**, creating needs **FilesCreate**, editing needs **FilesWrite**, and removing needs **FilesDelete**. Files is one of the areas that has no list definition of its own: the area is reached directly from the main menu. ## Related articles - [Using the Feed](/docs/product/files-and-collaboration/using-feed) - [Annotations](/docs/product/files-and-collaboration/annotations) --- ## Files & Collaboration URL: https://documentation.skillsworkflow.com/docs/product/files-and-collaboration Summary: Where the conversation about a piece of work happens, and how files are reviewed. # Files & Collaboration Work is discussed where it lives. The feed carries the conversation, the decisions and the files attached to a document. Annotations let reviewers mark up a file directly instead of describing changes in words. Chat carries the quick exchanges that do not belong to any one document. --- ## Filling in Time Sheets URL: https://documentation.skillsworkflow.com/docs/product/time/timesheets/filling-in-timesheets Summary: Verify that you can navigate by clicking on the time sheets section. To enter time, navigate to the **Time Sheets** module. 2. Verify that some lines appear on your grid automatically, based on the jobs you have been assigned to. 3. If you are not seeing the Job or Project that you need, click on the "+" to add a new entry to your timesheet grid. A popup will open. 4. Then use the search field at the top to quickly search for the job number, client name or any other key word. 5. On this popup you may find different tabs, depending on your accesses. 6. Each tab has a "Search" icon where you can easily filter the information. 7. You can also further filter a specific field by typing in what you are looking for under each column title 8. It is possible to specify the type of activitiy you have been doing (e.g. Research, meeting, etc.) for each time entry. Go to the work type column and select the work type for each line from the drop down list. 9. Check that the indicators, on the right side of your timesheet, change as you enter time. 10. Verify that you can add more details to your entries by clicking on the right button of your mouse and pressing "details". 11. Check that there are no red cells (invalid hours) 12. These can appear if you are exceding your maximum daily hours or if you are entering time on a level that you are not allowed to (e.g. if you enter time on a Project and you are only allowed to enter time on Jobs) 13. If that is the case, erase those hours and enter them again on the correct line 14. Click on the "+" if the entry you need is not on your timesheet yet 15. You may also be allowed or not to enter time on the weekend, holidays or leave days depending on your company's policy 16. Once you are ready, submit your timesheet for approval by clicking on the arrow, on the timesheet menu bar. 17. Verify that the color of the cells changes to light green. Wait for your supervisor to approve your timesheet. 18. Check the legend below the calendar for details. 19. Verify that there are no incomplete days/weeks. 20. Verify that there are no days pending submission for approval (days in blue) ## Related articles - [Time Sheet Timer](/docs/product/time/timesheets/timesheet-timer) - [Approving Time Sheets](/docs/product/time/timesheets/approving-time-sheets) - [Transfer hours between projects or jobs](/docs/product/time/timesheets/transferring-hours-between-projects) - [Planned Time](/docs/product/planning-and-scheduling/resourcing/planned-hours) --- ## FTE Workspace URL: https://documentation.skillsworkflow.com/docs/product/dashboards-and-reporting/fte-dashboard Summary: FTE which stands for Full-Time Equivalent is a unit that measures the workload of an employee. FTE which stands for Full-Time Equivalent is a unit that measures the workload of an employee. FTE is often used to measure an employee's involvement in a project. On this workspace, project managers can analyze FTE at different levels (ie company, division, department, typology group, employee). To access, select FTE under the Workspaces menu. The first section is the selection criteria where the following are defined: 1. Year 2. Company 3. Division 4. Department The next section is where you define the period you want to analyze. Slide the start and end date flags across the horizontal calendar to set the period. The last section is a list view showing "Users by Type Group, Department, and Division." It is presented in a hierarchy from Division to User levels that can be expanded or collapsed. The report has 4 column sections showing the following: People - Active: count with active status - FTE – (Capacity + Delivery Time + Vacation Time) / Working Hours - Capacity – Total working hours for the period – Total vacations in hours – Total vacations in hours Hired - Total: total hours sold in the rate proposal - % Capacity – (Total Contracted / Capacity) * 100 Billable + Forecast - Total: Actual Billable Hours + Forecast Hours - Forecast – Total Scheduled Hours - % Hired – (Total Billable and Forecast / Total Hours Hired) * 100 - % Capacity – (Total Billable and Forecast / Capacity) * 100 Actual - Total: Billable + Non-Billable - Billable – Customer - Non-Billable - Administrative - Administrative: Actual hours charged for administration tasks - Customer: actual hours charged to customers Expanding the Type Group level will display the Employees with that Type Group in that Department and Division. Expanding Employee will show the breakdown of your time charges by client. ## Related articles - [Resource Scheduler](/docs/product/planning-and-scheduling/resourcing/resource-scheduler) - [Filling in Time Sheets](/docs/product/time/timesheets/filling-time-sheets) --- ## Gantt URL: https://documentation.skillsworkflow.com/docs/product/planning-and-scheduling/gantt Summary: The Gantt shows a project's jobs on a timeline: building the schedule, selecting rows, duplicating jobs and editing several at once. The Gantt shows a project's jobs on a timeline, with the job hierarchy in a grid on the left. Rows in that grid can be selected and acted on as a group: duplicated, or edited together with a bulk action. One of the many ways of visualizing your Projects in Skills Workflow is in a Gantt Chart. The Gantt view will give a more visual representation of all the jobs of a Project and how they are related to one another through time. ## Create your parent and child Jobs 1. Start by creating Jobs inside your Project. 2. Under a parent Job you can also create many child jobs. ## Switch to Gantt View. 1. Inside the Project, on the tab "Jobs" click on this symbol. 2. Check your Jobs and their hierarchy on the left. 3. Check start and end date of each Job and adjust if needed.The system calculates duration of each job in days based on the start and end dates defined. 4. You can adjust your jobs by doing changes on the respective columns on the left or by directly moving the horizontal bars. 5. Drag them through the calendar to change the dates or strech/shrink them to lenghten/shorten the duration of the jobs. 6. Configure the dependency between the jobs by filling in the predecessor column. ## Check completeness of each job. - On the field "% Done" you can check how much has been done on a given job and whether it has already finished (100% done) or is still in progress (\<100% done). - These percentages are pre-defined based on the Workflow Stage the job is in. E.g. You can define that when a job reaches the stage "Waiting Client Approval " it is 70% complete. - As jobs move along the workflow to different stages, these % in the Gantt automatically change, but you can still manually adjust them if needed. - The colour of each bar represents the stage that respective job is in. The Gantt View includes several buttons at the top to help you adjust your chart view: - Every time you do a change you'll need to save the changes. - Zoom Out - Zoom In - Zoom to fit all of the information on the screen - Expand All to see the details of all Jobs - Collapse All to see only the Jobs (parents) - Add a new Job - Go to the selected Job ## JobType Dropdown - You can easily add Jobs to the Gantt without having to use the regular Job creation pop-up. - To add a new Job to the gantt, you'll need to select a Department/Job Type from the dropdown list. - When the Job Type is already selected click on the "Add Job" option and the job will be automatically added to the Gantt. - The job will only be activated as soon as you click on the "Save" option. - It will move to the first stage defined on the Workflow. ## Executors Column - On the Executors Column you can easily check who's been assigned to the jobs by passing your mouse on top of the image. - You can also easily assign users by clicking directly on the Executors column. The job will automatically open on the Assignments pop-up. - Search for a username or title and click on it to add as an executor. After this you'll need to submit the post. ## Copy & Paste the Gantt - Jobs can now be easily copied and pasted in order to quickly create Schedules. - Select the jobs you want to copy, click on the right side of the mouse and select the option Copy. - After this, paste the jobs by selecting the option "Paste". - You can also copy Jobs and paste them in other Projects. ## Pop-up message when leaving the project. Whenever you try to navigate to another module/tab without saving the changes you made, a pop-up message will appear alerting that there are unsaved changes. ## Availability The Gantt comes from a workspace, and its toolbar is off unless the workspace turns it on. Duplicate needs permission to create jobs. Bulk action needs permission to edit jobs, and the job must already be set up for bulk editing, as it is for list views. A button whose requirement is not met is hidden. ## Selecting rows The first column of the grid holds the selection checkboxes. They appear when you hover a row, and stay while the row is selected. Tick the checkbox in the column header to select every row. Ticking a parent selects everything under it. Clicking a row's WBS cell selects the whole row. Ctrl (Cmd on macOS) adds or removes one row. Shift extends from the last row you clicked. Clicking any other cell selects the cell, not the row. Selection column with a parent row and its children selected ## Duplicating jobs Select the rows and click **Duplicate**. The copies appear next to the originals in Draft, and become jobs when you click **Save**. A duplicated parent brings its branch with it, so selecting a parent together with its children still produces one copy of the branch. Duplicate leaves the **Copy row** clipboard untouched. Duplicated rows created in Draft below the originals ## Editing several jobs at once **Bulk action** opens the bulk editing dialog on the selected rows. It is the same dialog used in list views. Save the Gantt first. The dialog writes to the jobs directly, and the Gantt reloads when it closes. Bulk action applied to the rows selected in the Gantt ## Rules and behaviour With unsaved changes in the Gantt, a bulk action stops and Skills Workflow asks you to save. Rows you have not saved yet have no job behind them. A bulk action skips them and tells you how it went. One bulk action covers at most 100 jobs. Selecting more shows a message. Duplicated rows are lost if you leave the Gantt without saving. Skills Workflow warns you before you navigate away. Save stays disabled until there is something to save. ## Configuration On the Gantt component in the workspace: - `showToolbar` shows the toolbar, including Duplicate and Bulk action. - `bulkCapLimit` sets how many jobs one bulk action may cover. Without it the limit is 100. - `allowCreate` and `allowBulk` turn either action off for this Gantt. They otherwise follow the job's own permissions. ## Related articles - [Create a Project](/docs/product/projects-and-jobs/create-projects) - [Planned Time](/docs/product/planning-and-scheduling/resourcing/planned-hours) --- ## Invoice an Estimate URL: https://documentation.skillsworkflow.com/docs/product/commercial/estimates/invoice-an-estimate Summary: Estimates can be created as retainers, and the system will automatically display their values. ## Create retainer estimates Estimates can be created as retainers, and the system will automatically display their values. Please check how you can create the estimate on Lesson 1 under the "estimates" section. To generate a retainer estimate please navigate onto the estimate general info tab, check the "Recurrence" option and hit the save button. The system will display a new field named "Rep. Number" at the deliverable/client level. You can adjust the Rep.Number to the number of times the values need to be repeated. On the example below, the Rep Number field is marked as 6 (it's a 6 month retainer estimate) and the system will multiply both the cost values and the income values by the Rep Number. Please be aware that the values under Third Party, Expenses and Resources will be displayed with the same values. At the project level third-Party and expenses will be available under "Planned Costs" Resources will be available under "Planned Time" ## Related articles - [Create Estimate](/docs/product/commercial/estimates/create-estimate) - [Invoice Authorizations](/docs/product/billing-and-costs/billing/invoice-authorizations) - [Credit Notes](/docs/product/billing-and-costs/billing/credit-notes) --- ## Invoice Authorizations URL: https://documentation.skillsworkflow.com/docs/product/billing-and-costs/billing/invoice-authorizations Summary: You can create invoice orders in the system, and in this way inform the financial team to proceed with the creation / synchronization of the document to the… You can create invoice orders in the system, and in this way inform the financial team to proceed with the creation / synchronization of the document to the external financial system, and generate the final invoice. What the system generates is an invoice request, not a final invoice, it must always be generated in the financial system (Primavera, Sage, NAV, SAP, etc.). Definition of billing conditions: ### General conditions To issue a billing request, within the budget approved by the customer, you must navigate to the **billing conditions** option. If the commercial customer has the financial customer associated, the system will automatically suggest the customer and pre-defined payment terms. You can define the percentage of billing, reference (PO customer) and dates. Note that if you have more than one billing condition for most budgets, you can add as many lines as you like and even have different customers. After establishing the billing conditions you want to apply, navigate to the feed, and change the status of the workflow to bill, generating the necessary invoice authorization(s). ### Conditions for delivery You can define different billing conditions for the customer's deliverable lines. Therefore, if you have, for example, an annual fee budget, in which you generate an invoice monthly, you can make the annual billing plan, if you have the customer's PO. In the general billing conditions, you should click on apply to all. The system will apply the conditions defined in the general option to all deliverables to the customer. You can go to each of the lines, press the details option, and manipulate the information of each of the lines if necessary, setting for example the dates or PO. In the example mentioned above for annual billing plans, you must handle dates and PO's You can define conditions on the lines either by percentage or by value. If the billing conditions are the same for more than one approved line, when you go to the feed and adjust the flow to "bill" the system generates an invoice with two lines. If the billing conditions are different for all lines, the system will generate as many invoices as defined conditions. Note that the invoice authorization will be sent to the external financial system by issuing the final documents. If an integration with the financial system is activated, the number field will be external updated with the final number. You can import the PDF of the invoice, for quick access to the document sent to the customer. To validate the final document that your invoice authorization generated, you must validate the status of the document (integrated) and the field with the external number. To print you must navigate to the invoice permission document, clicking on the line you want to validate. The system will show the details of the document, values, contracted service, etc. To print just click on the pdf option in the upper right corner, and a PDF document will be generated that you can download and send by email if necessary ### Invoice authorization detail You can also consult the list of all your invoice authorizations by browsing the modules in the browser on your left. In the list of invoice authorizations you can apply several filters, such as: customer, project, budget. ## Related articles - [Invoice an Estimate](/docs/product/commercial/estimates/invoice-estimate) - [Credit Notes](/docs/product/billing-and-costs/billing/credit-notes) - [Purchase Orders](/docs/product/billing-and-costs/billing/purchase-orders) --- ## iOS App User Configuration URL: https://documentation.skillsworkflow.com/docs/product/mobile/ios-configuration Summary: Downloading the Skills Workflow app from the App Store and configuring it on an iOS device. To configure your Skills Workflow on iOS, first you will need to download our app from the App Store. To configure the app you should follow these few steps: - Open SkillsWorkflow App - On the Login Page tap on the Settings icon in the bottom right corner - Fill the site name given by your manager: (Ex: https://demo.skillsworkflow.com) - Select the Environment and Save ## Related articles - [Mobile Features](/docs/product/mobile/mobile-features) - [Android App User Configuration](/docs/product/mobile/android-app-config) --- ## Leaves My Department Workspace URL: https://documentation.skillsworkflow.com/docs/product/dashboards-and-reporting/leaves-my-department Summary: Al programar sus propias licencias o aprobar las licencias enviadas por sus subordinados, es importante saber si otros empleados del mismo departamento… Al programar sus propias licencias o aprobar las licencias enviadas por sus subordinados, es importante saber si otros empleados del mismo departamento también están de licencia. Esto evita que el departamento quede paralizado debido a que muchos empleados están de baja el mismo día. To access, select "Leaves - My Department" in the Workspaces and the current month's calendar will be displayed. To select the desired month, simply click the forward or back buttons next to the month display field. ## Related articles - [Approving Leaves](/docs/product/people/leaves/approving-leaves) - [Leaves Workspace](/docs/product/dashboards-and-reporting/leave-dashboard) --- ## Leaves Workspace URL: https://documentation.skillsworkflow.com/docs/product/dashboards-and-reporting/leaves-dashboard Summary: When scheduling our own leaves or approving leaves submitted by our subordinates, it's important to know if other employees in the company are also on leave… When scheduling our own leaves or approving leaves submitted by our subordinates, it's important to know if other employees in the company are also on leave on the same day. This prevents the company from being crippled due to a lot of employees being on leave on the same day. This workspace provides a calendar view showing which users from the same company are on leave on each working day of the calendar month. To access this workspace, select "Leaves" from the Workspaces menu and the current month calendar will be displayed. On the right side of the workspace is a table showing users whose leave submitted for that calendar month is still pending approval. To select the desired month simply click the forward or backward buttons beside the month display field. ## Related articles - [Scheduling Leaves](/docs/product/people/leaves/scheduling-leaves) - [Approving Leaves](/docs/product/people/leaves/approving-leaves) --- ## Manage List View URL: https://documentation.skillsworkflow.com/docs/product/projects-and-jobs/list-view Summary: By default you have the following sub-lists: You need to expand your view in order to be able to see all the available fields. ### In order for you to find what you are looking for in Skills Workflow, there is a menu on your left organized with different modules. 1. To navigate to each module just pass your mouse on each icon and a legend will appear identifying the respective module. 2. After that you just need to click on the module or select one of the sub-lists available. ### Whenever you are looking for a specific Job or simply want to search for a job who is grouped in one category, you can always use the sub-lists available. 1. In the Jobs module, there are several sub-lists that shows the different jobs organized by status. 2. These sub-lists are available for all users and can be configured according to each agency, meaning you can add new sub-lists to help you organize your jobs view. **By default you have the following sub-lists:** - All - In the sub-list “All” you can see all the jobs that you are involved with. - ClientRequests - In the sub-list "ClientRequests" you will see all the jobs requested by your clients. - Closed - All the jobs that are closed are automatically moved to the sub-list "Closed". - Delayed - In the sub-list “Delayed”, you may see all the jobs that are delayed. This means that the agreed date has passed and the Job is still not finished/closed. - Mine - All jobs that are created by you will automatically appear on the sub-list "Mine". - MyTeam - If you just want to check your Team's jobs, you will need to access the sub-list "MyTeam". - Pending - In the sub-list “Pending”, you can see the jobs that need your attention and action. For instance, assigning a user or sending for approval. ### Once you select the sub-list, you can always customize your own list view in order to organize the fields according to the relevance. You need to expand your view in order to be able to see all the available fields. For that you just need to click on the symbol that says "Expand". ### To customize your own view, you can drag and drop fields and organize the information according to your needs. 1. You can also remove or add more fields through the option "Column Chooser". For that you just need to click on the option . 2. A box list will pop-up, with all the available fields. To add or remove you just need to check or uncheck accordingly. ### You can also filter the available fields in order to see a specific stage, client, company, etc. 1. For that you just need to click on the symbol. 2. After that, you need to select the information you want to check and click ok. ## Related articles - [Create Jobs](/docs/product/projects-and-jobs/create-jobs) - [My Tasks](/docs/product/projects-and-jobs/my-tasks) --- ## Massively assign or unassign users URL: https://documentation.skillsworkflow.com/docs/product/people/teams/assign-users-in-bulk Summary: Follow the next steps to massively assign or unassign users on the Jobs' teams: If the intention is to unassign users from the jobs' teams, the process is the… Follow the next steps to massively assign or unassign users on the Jobs' teams: 1. Go to the tab "Jobs". 2. Select the desired Jobs from the list. 3. Click on the symbol to allocate users. 4. Select the option allocate users. - Choose the assignment type (e.g. requester, responsible, executor, etc.)* - Choose the intended user (you can type the name for easier finding) and click **OK** - Repeat this action if more users need to be assigned If the intention is to unassign users from the jobs' teams, the process is the same, but select the option remove allocated users instead. ## Related articles - [What is a Team and what does each Group represent?](/docs/product/people/teams/what-is-a-team) - [Create Jobs](/docs/product/projects-and-jobs/create-jobs) --- ## Missing Time Hours and Approvals Workspace URL: https://documentation.skillsworkflow.com/docs/product/dashboards-and-reporting/missing-hours-and-approvals Summary: This workspace provides real-time information on users blocked due to missing hours and/or missing timesheet approvals from their subordinates. This workspace provides real-time information on users blocked due to missing hours and/or missing timesheet approvals from their subordinates. Para acceder, seleccione "Horas de Tiempo en Falta y Aprobaciones" en el menú del Timesheet. The workspace has 2 sections that show the following: Graphics 1. Blocked Users – A bar chart showing the number of users blocked by missing hours and missing approvals. Hovering over the bar will display the number of users. 2. Blocked Users by Department - A pie chart showing the percentage breakdown by department in the number of blocked users. Hovering over the graph will display the number of blocked users in the department. 3. Total Hours of Missing Time- A bar graph showing the number of hours in arrears for Missing Hours and Missing Approvals. Hovering over the bar will display the number of hours past due. 4. Missing Hours by Department: A pie chart showing the percentage breakdown by department in the number of hours overdue. Hovering over the graph will display the number of hours delinquent in the department. Blocked Users List and Missing Time Hours A list showing blocked users in each department with the following columns: - Username –Skills User Blocked name - AD Username: Active Directory username of the blocked user - Timesheet Required – Checkbox to indicate if locked user with timesheets is required - Locked In System – Checkbox showing that the user is locked in Skills - AD Locked – Checkbox showing that the user's AD is locked - Reason for Blocking – Reason for Delinquency either Hours of time in lack and approvals - Missing Hours: Total hours in arrears to date - Days left: Click on the display bar and a window will pop up showing the days left ## Related articles - [Approving Time Sheets](/docs/product/time/timesheets/approving-time-sheets) - [Filling in Time Sheets](/docs/product/time/timesheets/filling-time-sheets) --- ## Mobile URL: https://documentation.skillsworkflow.com/docs/product/mobile Summary: The iOS and Android apps, and how each user sets them up. # Mobile Skills Workflow has apps for iOS and Android. This area covers what the apps can do, and the configuration each user does on their own device. --- ## Mobile Features URL: https://documentation.skillsworkflow.com/docs/product/mobile/mobile-features Summary: Skills Workflow Mobile app is available on all iOS and Android devices. Skills Workflow Mobile app is available on all iOS and Android devices. The app accompanys the use of the Web and is constantly being improved and updated. Here is a list of current modules and features available on the app. Current modules: - Projects - Jobs - Expenses - Notifications - Timesheets ### Search Tap on the search bar and type something to perform a system general search. Tap on the available modules in the system and select from respective lists to show results. Type something with the filter on to search within any module. Note: Open, view and navigate through documents. Select and open a document to see its information. Different documents will have different tabs, these are currently available: - Feed - Info - Team - Files - Checklist - Additional Info - Jobs - Expenses Actions After opening your document you can easily perform document actions by tapping on "What do you want to do?" in the Feed tab. This will open a new comment page where all actions will be added. Tap on the sliding menu to see all options: - Move stage - Add images - Assign People - Change End Date - Add time - Notify people - Additional Information When you are done, tap ok and post your changes to the document. Note : Create Documents The mobile app will have document creation just like in the Web. To do this navigate to the desired document parent and tap on the top right corner "+" to create a new document underneath it. Currently available documents for creation: - Expenses. The timesheet calendar will give you an overview of your hours. Select a day and add time to a document. Enter Timesheet details if you need. That's it. ## Related articles - [iOS App User Configuration](/docs/product/mobile/ios-app-config) - [Android App User Configuration](/docs/product/mobile/android-app-config) --- ## My Tasks URL: https://documentation.skillsworkflow.com/docs/product/projects-and-jobs/my-tasks Summary: Once you complete all the fields click on the option 'check'. ### In Skills Workflow you can create tasks for yourself (if configured at your company). - Tasks are regular jobs that behave a little bit differently throughout the system. - They are created the same way as regular jobs but the workflow is usually much simpler (e.g. To Do> Done). - They are also typically on a separate list for easier consultation. ### Create a new Task 1. To create a new Task, navigate to the "Projects" module. 2. Select the active Project where you want to include the new Task under. 3. Inside the Project's page click on the "+" sign and option "Job". ### Filling in the Task creation popup form. - **Title** - Name you would like to give to the Task. - **Department** - Choose Task (this defines that this job is actually a task). - **Type** - Type of task you want to create- - **Start/End** - Choose when the Task starts and when it will end. Once you complete all the fields click on the option 'check'. ### Add a Description and upload files 1. Just type in all the information on the description inside the new Task creation popup. 2. At any time you can change the Description. For that you just need to click on the option that says "Edit". 3. You can also attach files such as images, emails, pdfs, by dragging or clicking on the dotted square. After filling in all the information, you will need to activate the Task. ### Activate Task 1. To activate it and generate a Task number, close the Task form by clicking on the check, and then on the bottom right side of the popup click on the small blue arrow. 2. A pop-up will appear saying it was successfully created. Click on this message to navigate directly to the Task. ### Add a checklist to your Task You can add a list of smaller items inside your task in the form of a checklist. 1. On the Task's feed click on the symbol. 2. Fill the name of the item you want to add. 3. It will appear with a checkbox on the Task's Description at the top. 4. Once that item is complete you can mark it as such by checking the box. 5. You can also check all items and delete items previously added on the tab "Items" at the top. ### Close the Task 1. Once the task is complete, you can close it yourself. 2. For that you just need to click on the symbol and select the available option. 3. Then click on the blue arrow on the feed post bar to make the status change effective. 4. The status change will stay posted on the task's feed. ### Check the "My Tasks" list - On the Skills menu bar, under Jobs you will find a list called My Tasks. - This list contains all your tasks. - Users will only be able to see their own tasks or tasks they've been assigned to. ## Related articles - [Manage List View](/docs/product/projects-and-jobs/list-view) - [Filling in Time Sheets](/docs/product/time/timesheets/filling-time-sheets) --- ## Notification Types URL: https://documentation.skillsworkflow.com/docs/product/notifications/notification-types Summary: Skills Workflow sends out two different types of notifications: Depending on their categories, notifications can have different periodicities: Regardless of… Skills Workflow sends out two different types of notifications: - E-mail notifications - In-system notifications Depending on their categories, notifications can have different periodicities: - Immediate (every 5 minutes) - Daily (once a day) - Weekly (once a week) Regardless of being immediate, daily or weekly notifications, all notifications are received in the system and can be sent via e-mail if the "Receive E-mail Notifications" flag is enabled on the user form. ## Immediate Notifications The immediate notifications are received in the system over a span of time of up to 5 minutes. These are mostly about posts generated on a specific document and are of the following categories: - Changes to workflow stages; - Changes to document teams; - Changes to document dates; - Comments added to document feed; - Tagging notifications on the document feed; - Leave approvals/disapprovals; - Timesheet disapprovals; - Password resetting; ## Daily Notifications The daily notifications are seen as a daily reminder to users. These are sent every day, at a specific time, according to what is set on the "Assistant Alert Time" field and calculated based on the "Default Time Zone" field in the back-office maintenance section. These notifications are of the following categories: 1. Pending timesheet hours and tolerance days left; 2. Pending timesheet approvals; 3. Pending leave approvals; 4. Delinquency and blocking alert due to missing timesheet hours: 5. To the responsible regarding the resources they are responsible for; 6. To the resources themselves; 7. Blocking confirmation due to missing timesheet hours: 8. To the responsible regarding the resources they are responsible for; 9. To the resources themselves; ## Weekly Notifications Leaves scheduled for the week after the current one: According to the "Leaves Notification Week Day" configuration in the maintenance module of the back-office, the responsibles will receive one single notification on a specific day of the week informing which resources they are responsible for will be on leave on the following week; ## My Notifications In Skills Workflow it is now possible to select which notifications a user wants to receive based on the role they play. This means that a user can opt to receive notifications as a user perspective or as a responsible. My Notifications: - Push - Email - Timesheets - Leaves - Documents - Digest Email Responsible Notifications: - Expiring Timesheets - Expired Timesheets - Timesheets to Approve - Leaves to Approve ## Related articles - [Using the Feed](/docs/product/files-and-collaboration/using-feed) --- ## Notifications URL: https://documentation.skillsworkflow.com/docs/product/notifications Summary: What the platform notifies people about, and through which channel. # Notifications The platform tells people when something needs their attention. This area covers the notification types, the categories they fall into, and how often each is sent. --- ## People URL: https://documentation.skillsworkflow.com/docs/product/people Summary: Who is on a team, what each group does, and how leave is scheduled and approved. # People Every project and job has a team, and each member belongs to a group that determines what they can do. This area covers those teams and groups, assigning people in bulk, and the leave cycle: scheduling it, and approving it. --- ## Planned Time URL: https://documentation.skillsworkflow.com/docs/product/planning-and-scheduling/resourcing/planned-hours Summary: After creating your Project, you can start planning the amount of time that each resource will spend on this Project. After creating your Project, you can start planning the amount of time that each resource will spend on this Project. 1. Go to the **Planned Time** tab inside your Project. 2. Click on the plus sign to add a new row to your planned hours table. 3. On the User column, select the specific person that you would like to plan the hours for. 4. The person's typology (i.e. position) will appear automatically on the Typology column. 5. On the column Planned, enter the amount of hours planned for that person. 6. Repeat these steps until you have all the people that you need. Alternatively, you may plan the hours for a generic typology without selecting a specific person. 1. To do so follow the first two steps as explained above. 2. On the Typology column select the position that you need to plan the hours for. 3. Do not fill in the user column. 4. On the column Planned, enter the amount of hours planned for that typology. 5. Repeat these steps until you have all the needed typologies. Once people start entering timesheets for this Project and/or jobs belonging to this Project, those hours will immediately show up on the Actual column. You will be able to track the planned vs actual hours in real time for your Projects. Planned hours typically come from the Fee with the client, and as such the system has specific roles that control whether a user has permission edit this column or not. **You can also do monthly forecasts by filling in forecasted figures under each month column.** The column called Forecast will show you the sum of all monthly forecasts. The column Actual and Forecast will show the sum of all monthly forecasts with the actuals up to the previous month (i.e. excluding the current month actuals shown on the stripped column). **On the timesheet grid you may find a column called Remaining time** **(if this setting is turned on for your company).** This column will show the remaining planned time allocated to you specifically, or to your position. ## Related articles - [Gantt](/docs/product/planning-and-scheduling/gantt) - [Resource Scheduler](/docs/product/planning-and-scheduling/resourcing/resource-scheduler) - [Filling in Time Sheets](/docs/product/time/timesheets/filling-time-sheets) --- ## Planning & Scheduling URL: https://documentation.skillsworkflow.com/docs/product/planning-and-scheduling Summary: Putting dates and people against the work: the Gantt, the resource scheduler and planned time. # Planning & Scheduling Once the work exists, it has to be scheduled and staffed. The Gantt puts a project's jobs on a timeline and sets the dependencies between them. The resource scheduler assigns people to that work and shows who is over- or under-loaded. Planned time records how many hours each person is expected to spend. --- ## Price Tables URL: https://documentation.skillsworkflow.com/docs/product/commercial/rates/price-tables Summary: A Price Table holds the prices used when quoting work, scoped to a company and a currency and valid between a start and an end date. # Price Tables A Price Table holds the prices used when work is quoted. It is its own area in the main menu, and a Fee must be associated with one. ## Availability Opening Price Tables needs the **PriceTableNavigate** permission; viewing one needs **PriceTableRead**, creating one needs **PriceTableCreate**, and editing one needs **PriceTableWrite**. ## Working with a price table A price table's own fields are its **Name**, **Company**, **Currency**, **Start Date**, **End Date** and **Stage**. The dates bound the period the table is valid for. A price table also has **Info**, **Files** and **Feed** sections, and can carry workspaces. ## Related articles - [Create Rate Cards](/docs/product/commercial/rates/rate-cards) - [Fees](/docs/product/commercial/fees) - [Create Estimate](/docs/product/commercial/estimates/create-estimate) --- ## Project Burn Workspace URL: https://documentation.skillsworkflow.com/docs/product/dashboards-and-reporting/project-burn-dashboard Summary: Workspaces are a powerful feature used to quickly support decisions related to a specific client or project. Workspaces are a powerful feature used to quickly support decisions related to a specific client or project. The goal is to give the user the ability to control processes in a very friendly and comprehensive way. As a project manager, it is very useful to understand the status of a specific client and control the profitability of each project. This way the PM will have the necessary tools to negotiate with their clients. There are several workspaces at the project level available in the system that will display different information. ### Burn Workspace 1. Select the project you want to analyze; 2. Click on the "Burn Workspace" tab; 3. You will find several representations that will show you in a glimpse whether your project is already burned. Please note that the burn workspace is based on Forecast versus Real hours. #### Time Burn This representation shows the number of forecasted hours versus number of real hours. Although the graphic is distributed per month, it also shows a sum representation. #### Revenue Burn This representation shows if the project is already burned in a revenue and costs perspective. Revenue values are based on planned/contracted hours and the associated value for each typology group. The cost values are inherited by the user cost versus number of real hours filled in. #### Typology Group Burn This Workspace shows which typology is burning your project and is based on actual hours. #### Department Burn This representation is based on the users' actual hours and shows which department is filling in more hours under a specific project. #### User Burn This representation is based on the users' actual hours and shows which user is filling in more hours under a specific project. ## Related articles - [Create a Project](/docs/product/projects-and-jobs/create-projects) - [Planned Time](/docs/product/planning-and-scheduling/resourcing/planned-hours) --- ## Projects & Jobs URL: https://documentation.skillsworkflow.com/docs/product/projects-and-jobs Summary: Creating projects, breaking them into jobs, and following the work in the list view. # Projects & Jobs A project is the container for a piece of client work; jobs are the individual pieces of work inside it. This area covers creating both, and the two views the team uses to follow them day to day: the list view, and each person's own task list. --- ## Projects on a Fee URL: https://documentation.skillsworkflow.com/docs/product/commercial/fees/projects-on-a-fee Summary: Creating a Project against a Fee, planning its hours, and tracking burn by typology group. A Project can be associated with a Fee, so that hours sold under that Fee are deducted as the Project's own hours are planned. Creating a new Project or Estimate from a Fee 2. Fill in the project header. - Title - Add a name for this project. - Type - Select the type of project from the dropdown list. - Start and End Dates - Select the date range for this project. - Project Owner - Select the user responsible for this project. - Fee - Select the Fee you want to associate with this project. - Deliverable - Select the deliverable that you want to associate with this project (estimated deliverables). Click the check icon to submit. Project header, with its Fee and Deliverable fields 3. After the project is created, navigate to the **Planned Time** tab and fill in the form with the following information: - Contracted Hours - Click the "Get Contracted Hours" symbol to fill this column with the hours approved on the associated Fee. - Planned Hours - Adjust the planned hours for this project, if they differ from the contracted hours. - Projection - Click the "Planned Hours Projection" symbol to distribute the planned hours over the project's date range. Planned Time, by typology group 4. Analyze the information on the Burn Workspace: - Check the number of hours planned for each typology group. - Check the number of hours filled by all users included in that project. - Check the number of hours available for each typology group. - Check the % of utilization by typology group. Burn Workspace, by typology group ## Related articles - [Fees](fees.md) --- ## Purchase Orders URL: https://documentation.skillsworkflow.com/docs/product/billing-and-costs/billing/purchase-orders Summary: Recording a commitment to buy from a supplier, tracking it against an estimate, and generating a Supplier Invoice or Supplier Note from it. # Purchase Orders A Purchase Order records a commitment to buy goods or a service from a supplier. It carries a name, a start date and a delivery date, a currency, and a stage that tracks it through your workflow. ## Availability Purchase Orders is its own area in the main menu. Opening it needs the **PurchaseOrderNavigate** permission; viewing a purchase order needs **PurchaseOrderRead**, creating one needs **PurchaseOrderCreate**, and editing one needs **PurchaseOrderWrite**. A purchase order can also be tied to an estimate, and shows up in that estimate's own Purchase Orders list. ## Working with a purchase order The **Info** section holds the purchase order's own fields: Name, Start Date, Delivery Date, Currency, and whether it has been marked Invoiced. The **Items** section holds what is actually being bought, as separate lines. A purchase order also has **Files** and **Feed** sections, like other documents in Skills Workflow. ## Stage A purchase order moves through the stages configured for its workflow. Available stage types include `Draft`, `New`, `Sent`, `ToEmit`, `Invoiced`, `NotExpectingInvoice` and `PartiallyInvoiced`. Which of these a workflow uses, and in what order, is set up per workflow. ## Invoicing a purchase order From the Purchase Orders list, select one or more purchase orders and click **Invoice**. Skills Workflow generates a Supplier Invoice or a Supplier Note from each one and marks the purchase order Invoiced. ## Related articles - [Create an estimate](../../commercial/estimates/create-an-estimate.md) --- ## Rejecting Time Sheets URL: https://documentation.skillsworkflow.com/docs/product/time/timesheets/rejecting-timesheets Summary: It's also possible to reject all by clicking X icon in the right upper side next to the check icon. In the same workspace where **time sheets** are approved 2. To reject a group, just has in **Time sheet Approval**. On the group bar click the X icon. 3. Only by clicking the X icon in the right upper side next to the check icon after you select the intended timesheets. ## Related articles - [Approving Time Sheets](/docs/product/time/timesheets/approving-time-sheets) - [Time Sheet Approval Levels](/docs/product/time/timesheets/multi-approving-time-sheets) --- ## Reports URL: https://documentation.skillsworkflow.com/docs/product/dashboards-and-reporting/reports Summary: Reports is its own area in the main menu, gated by the Report permissions. # Reports Reports is its own area in the main menu, reached at `reports`. ## Availability Opening Reports needs the **ReportNavigate** permission; viewing a report needs **ReportRead**, creating one needs **ReportCreate**, and editing one needs **ReportWrite**. Like Files, Reports has no list definition of its own — the area is reached directly from the main menu. ## Related articles - [Workspaces & Reporting](/docs/product/dashboards-and-reporting) --- ## Resource Scheduler URL: https://documentation.skillsworkflow.com/docs/product/planning-and-scheduling/resourcing/resource-scheduler Summary: Plan your team on a timeline: assign tasks by dragging them onto a person, book hours per day, read capacity, and see leaves, holidays and reservations alongside the work. The Resource Scheduler puts your team on a timeline. Each row is a person, each bar is work booked against them, and the panel on the right holds the tasks still waiting for someone. You assign work by dragging it onto a row, adjust it by dragging or resizing the bar, and read each person's load from the capacity figures beside their name. The Resource Scheduler, with the resource column, the timeline and the tasks panel ## Reading the board The resource column on the left carries each person's photo, name and typology, a utilization bar and a percentage. The board opens grouped by typology; the **Group By** button changes that. Weekend and non-working columns are shaded, and stay shaded whichever zoom you are on. A bar is coloured by the stage of its task, dimmed, with the full stage colour down its left edge. The **Color** entry in the ⋮ menu repaints them by user, project owner or creator instead. What a bar can carry: | Mark | Meaning | |---|---| | Client logo | The client the task belongs to. | | `NEST0018CR001 - Storyboard` | The task's number and name. | | A coloured gauge icon | Priority: green low, orange normal, red high. | | A repeat icon in the header | At least one day on the bar is part of a recurring series. | | A repeat icon inside a day cell | That day is a recurring occurrence. | | A layers icon inside a day cell | That day holds more than one booking. | | `03:00` in a day cell | Hours booked on that day. | | A thin strip above each day | How full that day is against the person's required hours. | | A purple pill | The project. | | A grey pill | The work type. | Bars also carry state. A **faded** bar is work whose hours are still booked on someone who is no longer assigned to it. A **hatched** bar was filtered out by a work-based filter. A **grey bar with a spinner** is being created, and a dimmed one is being saved. ### Kinds of bar Not every bar is a task. **Administrative bars** carry a briefcase icon, a name and a work type, and no task number. They are time booked against a work type rather than against client work, for things like production or training. Create one by dragging across empty space and choosing **Workload** without picking a task. **Reservations** are flat bars with a bookmark icon, coloured by priority. They hold days for a person without pointing at any task. **Leave, holidays and non-working days** are drawn alongside the work so absence is visible while you plan. ## Who and what appears Rows are the active users you are set as Responsible for, plus your own. Someone with no team of their own still sees their own row and their own bookings. Only deliverables marked **Plannable** can be planned here. That flag is set on the deliverable itself. Work in the stages the workspace excludes never reaches the board. Out of the box those are `Cancelled`, `Draft` and `Closed`. ## Tasks mode and Workloads mode The **Mode** entry in the ⋮ menu switches how the bars are drawn. In **Tasks** mode a bar is a whole task on that person, from its first to its last day, with one cell per day for the hours booked. In **Workloads** mode a bar is a single booking, and moving it moves that booking alone. Both modes accept the same gestures. Tasks mode is the one to use when you are placing work and shaping its span; Workloads mode when you are rebalancing hours that are already booked. ## Assign a task 1. Open the tasks panel on the right. 2. Find the task in **Unassigned** or **All Tasks**. 3. Drag it onto the person and the day you want. The **Add Workload** editor opens with the task, the person and the day already filled in. Set the hours and save. **Unassigned** lists plannable tasks in the visible window that nobody is booked on. **All Tasks** searches the whole plannable pool, including work already assigned to someone. The number beside the toggle counts the rows currently listed, and the search box filters whichever list is showing. Each row shows the task's number and name, with its project and client underneath. The list is bucketed by when the work is due: | Group | Holds | |---|---| | **Delayed** | Tasks whose agreed date falls before the visible window. | | A week's date | Tasks due in that week. | | **Next** | Tasks due after the visible window. | | **No Date** | Tasks with no agreed date. | Double-clicking a row in the panel opens that task's preview rather than assigning it. The tasks panel ## Move, extend and copy work Drag a bar sideways to move it to other dates. Drag it onto another row to hand the work to that person. Drag its left or right edge to lengthen or shorten it. Hold **Shift** while dragging onto a second person to copy the booking to them and keep the original. If a move or resize takes work outside the task's current dates, you are asked *Do you want to add the Task to the dragged date?* before those dates are stretched. Narrowing a task's span asks before it clears hours that other people have booked outside the new range, and names them. Moving a workload that several people share asks whether to apply the move to that one person or to everyone in the group. ## Book hours per day Every task bar carries one cell per day it covers. Click a cell to open the workload editor for that day, then enter the hours. Days with hours booked show them as `hh:mm`. A cell marked with a layers icon already holds more than one booking that day. The number shown is their total, and hovering lists each one with its hours, work type and start time. ## Create work on the board Drag across empty space on a person's row. Where more than one kind is available, you are asked which to create: Choosing what to create **Workload** opens the Add Workload editor on the dragged day, with that person already on it. Pick a task to book time against client work. Leave the task empty and pick a work type instead to book administrative time, which is what draws the briefcase bars. **Task** opens the job create form with the dragged dates already filled in. Once the task is created the workload editor opens on it, and it is there that the hours are booked and the person is assigned. Cancel at that second step and the task still exists, waiting in the Unassigned list. **Reservation** asks for a description, then for a priority of **Low**, **Medium** or **High**. It blocks the dragged days for that person without pointing at any task. With only one kind available the drag goes straight to it and nothing is asked. Which kinds are offered depends on the workspace parameters and on your roles. ## The Add Workload editor Every path that books time opens the same editor: the drop from the tasks panel, a click on a day cell, and the **Workload** drag-create. Assign workloads It does more than take a number of hours: | It can | Effect | |---|---| | Book several people at once | The booking becomes a shared group. Moving it later asks whether the change applies to one person or to everyone in the group. | | Book a range of days | The hours are spread across every day in the range rather than the single day you started from. | | Repeat the booking | A recurring series with its own end date. Days in a series carry a repeat icon, and are edited and deleted as a series. | | Set a work type | Required when there is no task. Optional on a task, where it appears as a grey pill on the bar. | | Set hours per day, or a start and an end time | Start and end times only apply in Day view. Elsewhere the booking is hours against the day. | | Carry a description | Shown when hovering the booking. | | Move the task to another stage | The transition runs when you save, and the bar is repainted in the new stage's colour. | When you edit a booking that covers several days, **Apply changes to** decides whether the edit hits the day you opened or every day on the bar. ## Right-click a bar Right-clicking offers the actions that apply to what you clicked. | Action | Effect | |---|---| | **Open** | Opens the task preview. | | **Delete this day** | Removes the hours booked on the day under the pointer. | | **Delete all days** | Removes every booking on the bar. | | **Delete** | Removes the workload, or the whole series when it recurs. | | **Unassign** | Removes the person from the task. | Unassigning someone who has hours booked from today onwards asks whether to remove them. Answer **No** and the hours stay on the board, drawn faded with nobody assigned. Double-click a bar to open the task preview. A reservation opens its own menu instead, where you can change its description or priority, or delete it. ## The toolbar The scheduler toolbar **Filter resources...** narrows the board. Its options are grouped by category. Resource, Company, Department, Typology, Responsible and Tags come from the people. Deliverable Tags, Stage, Project, Client and Task come from the work. A person-based filter hides rows; a work-based filter keeps the row and hatches the bars that do not match. The funnel button filters by load: **All Users**, **Overbooked Only** (above 100%) or **Available Only** (100% or below). **Group By** stacks rows under headings. The choices are None, Company, Department, Typology, Project, Task (by Date), Client, Stage, Agreed Date and Task (by Priority). The date box sets the anchor of the visible window. Its arrows step one period back or forward, and its calendar picks any single day at any zoom. Four buttons set the span: | Zoom | Window | |---|---| | **Day** | One day, on an hour axis. | | **Week** | Seven days from the first day of the week. | | **Work week** | The same week with its weekend off the axis. | | **Month** | 28 days, starting a week before the picked date. | ### More options The ⋮ menu holds: - **Mode**, switching between Tasks and Workloads. - **Color**, painting bars by **Stage**, **User**, **Project Owner** or **Created By**. - **Time format (12h / 24h)**, which changes the hour axis and the tooltips. Durations are never reformatted: 8.5 hours stays `08:30`. - **Role**, which picks the assignment type stamped on the assignments and workloads you create here. It does not change what the board shows. - **Show approved Leaves only.**, hiding leave still waiting for approval. - **Contracted Time**, overlaying contracted hours from estimates. This entry is only offered to users with the `EstimateRead` role. - **Show Tasks Panel** / **Hide Tasks Panel**, **Refresh** and **Export to Excel**. When the window is too narrow for the whole toolbar, the zoom and capacity buttons move into this menu. ## Capacity and availability Beside each name is a utilization bar and a percentage, green up to 100% and red above it. Daily capacity comes from the hours set on each user. The capacity buttons choose the overlay drawn across the timeline: | Overlay | Shows | |---|---| | **No capacity overlay** | Bars only. | | **Capacity bar** | A utilization bar per day. | | **Heatmap (%)** | Each day shaded by how full it is. | | **Hours** | The hours booked on each day. | Heatmap and Hours add a summary row above each person's bars. While either is on, **Expand all users** and **Collapse all users** appear on the toolbar, and clicking one summary row collapses that person alone. Hovering a capacity cell reports the hours booked and free on that day, and the hours still free that week. The heatmap overlay, with a capacity tooltip open ## Leaves and holidays Hovering a leave or a holiday shows its type and date, and its duration as **Half Day**, **Full Day** or as hours when the leave type is recorded in hours. Any description or motive appears underneath. ## Rules and behaviour Leave, holiday and non-working-day bars cannot be moved or resized. Recurring workloads cannot be dragged or resized. Edit them through the workload editor. A workload cannot exceed 24 hours in a day, and a day that has reached the person's maximum daily hours refuses new ones. You cannot add workloads to a task you are not assigned to. When your company does not allow planning on weekends, Saturday and Sunday refuse new workloads. Copying a task onto someone already assigned to it is refused. Permissions apply to the gestures as well as the screens: | Action | Role required | |---|---| | Change who a task is assigned to | `ExecutorAssignmentSave` | | Change a task's dates by dragging or resizing | `DeliverableWrite` | | Create a task from a drag | `DeliverableCreate` | | Create a reservation | `ReservationCreate` | | Edit or delete a reservation | `ReservationWrite` | | See the Contracted Time overlay | `EstimateRead` | ## Configuration The scheduler is a workspace, and its behaviour is set through the workspace's parameters. Values below are the ones it ships with. | Parameter | Effect | |---|---| | `DefaultMode` | Starting mode, `tasks` or `workloads`. Ships as `workloads`. | | `DefaultGroupBy` | Grouping applied before the user picks one. Ships as `typologyGroupName`. | | `DefaultTeam` | Assignment type the Role menu starts on. Ships as `Executor`. | | `WeekStartDay` | First day of the week, `0` for Sunday. Ships as `1`. | | `HourFormat` | Starting clock, `12` or `24`. Ships as `24`. | | `EntryTime` | Time of day stamped on a workload when the editor sends none. Ships as `09:00`. | | `StagesToExclude` | Stages kept off the board. Ships as `Cancelled,Draft,Closed`. | | `BusinessObjectTypes` | Types that can be planned from. Ships as `Job,Task,Deliverable`. | | `ConfirmJobDateExtension` | Set to `0` to stretch task dates without asking. | | `DragCreateWorkload`, `DragCreateTask`, `DragCreateReservation` | Set one to `0` to drop that option from the drag-create prompt. | | `WorkloadEditorWorkspaceId` | The workspace opened as the workload editor. | A user's own toolbar choices are remembered and take precedence over these defaults on their next visit. ## Related articles - [Planned Time](/docs/product/planning-and-scheduling/resourcing/planned-hours) - [Gantt](/docs/product/planning-and-scheduling/gantt) - [Utilization Dashboard](/docs/product/dashboards-and-reporting/utilization-dashboard) --- ## Scheduling Leaves URL: https://documentation.skillsworkflow.com/docs/product/people/leaves/scheduling-leaves Summary: To schedule Leaves, click on the Leaves modules and choose the option “Scheduler”. Navigate to the **Leaves module**. ## Choose Leave Type 1. You will find a list of different leave types to choose from on the list that says “Type”. 2. Verify that the indicators on the right change as you change the selected leave type. ## Select desired days Click on the days you want to book. There is no need to save. The system automatically saves it for you. ## Create leave form - To associate a leave form to a day or group of days, click on the "New leave form" button on the Leaves Scheduler menu bar - Verify that the leave form pop-up opens. - Select the day or days (From - Until) - Check the option half day if you're applying for a half day leave - Add a description - See the associated approvers - See the leave's history - Attach a file ## Send for approval - To send for approval click on the check icon on the leaves menu bar. - Check the description box on the right to verify that the selected days have changed colour accordingly. ## Related articles - [Approving Leaves](/docs/product/people/leaves/approving-leaves) - [Leaves Workspace](/docs/product/dashboards-and-reporting/leave-dashboard) --- ## Supplier Invoices URL: https://documentation.skillsworkflow.com/docs/product/billing-and-costs/billing/supplier-invoices Summary: A Supplier Invoice records an invoice received from a supplier, and can be generated automatically from a Purchase Order. # Supplier Invoices A Supplier Invoice records an invoice received from a supplier. It is its own area in the main menu, and moves through the stages configured for its workflow. Supplier Invoices are also created for you when you invoice a Purchase Order: selecting purchase orders and clicking **Invoice** generates a Supplier Invoice or a Supplier Note from each one. ## Availability Opening Supplier Invoices needs the **SupplierInvoiceNavigate** permission; viewing one needs **SupplierInvoiceRead**, creating one needs **SupplierInvoiceCreate**, and editing one needs **SupplierInvoiceWrite**. ## Working with a supplier invoice A supplier invoice carries an emission date, a due date and a **Stage**. It also has **Files** and **Feed** sections, and can carry workspaces. ## Related articles - [Purchase Orders](/docs/product/billing-and-costs/billing/purchase-orders) - [Supplier Notes](/docs/product/billing-and-costs/billing/supplier-notes) - [Bills](/docs/product/billing-and-costs/billing/bills) --- ## Supplier Notes URL: https://documentation.skillsworkflow.com/docs/product/billing-and-costs/billing/supplier-notes Summary: A Supplier Note is the credit-note counterpart to a Supplier Invoice, and can be generated automatically from a Purchase Order. # Supplier Notes A Supplier Note is the supplier-side counterpart to a Supplier Invoice. It is its own area in the main menu, and moves through the stages configured for its workflow. Like Supplier Invoices, Supplier Notes are also created when you invoice a Purchase Order. ## Availability Opening Supplier Notes needs the **SupplierNoteNavigate** permission; viewing one needs **SupplierNoteRead**, creating one needs **SupplierNoteCreate**, and editing one needs **SupplierNoteWrite**. ## Working with a supplier note A supplier note carries an emission date, a due date, an **Entry Date** and a **Stage**. It also has **Files** and **Feed** sections, and can carry workspaces. ## Related articles - [Supplier Invoices](/docs/product/billing-and-costs/billing/supplier-invoices) - [Purchase Orders](/docs/product/billing-and-costs/billing/purchase-orders) --- ## Time URL: https://documentation.skillsworkflow.com/docs/product/time Summary: Recording the hours actually worked, and getting them approved. # Time Planned time says what should happen; time sheets record what did. This area covers filling in a time sheet, the timer, moving hours between projects, and the approval path a submitted time sheet follows. --- ## Time Sheet Approval Levels URL: https://documentation.skillsworkflow.com/docs/product/time/timesheets/approval-levels Summary: If the approval type is the same for all clients, the timesheet approval type should be selected at the company level. ### Company If the approval type is the same for all clients, the timesheet approval type should be selected at the company level. ### Client If the timesheet approval is different per customer: Go to maintenance, select the client, choose the timesheet approval type and hit save. ### User Maintenance – Users – responsible – you can set up 1 or several responsible for timesheet approval, you should also set their respective order. ### PM Approval If the timesheet approval process is set to be approved by the project manager, every time that a user fills in hours and send it to be approved it flows to the project PM, after the PM approves it flows to the user responsibles. If you set up different approval responsibilities (different orders) the system will always check that hierarchy. If one of the responsible reject the hours, all the hierarchy will see them as rejected, and will be able to see the tool tip with the motive. Once the PM approves the hours will flow to the responsible order 0 to be approved. Once the user responsible order 0 approves, the hours flow to the responsible order 1 to be approved. Administrative hours are sent to the user responsible set on the user info. ## Related articles - [Approving Time Sheets](/docs/product/time/timesheets/approving-time-sheets) - [Rejecting Time Sheets](/docs/product/time/timesheets/rejecting-time-sheets) --- ## Time Sheet Timer URL: https://documentation.skillsworkflow.com/docs/product/time/timesheets/timesheet-timer Summary: The Timesheet Timer lets you track the time you spend on a document in real time. The Timesheet Timer lets you track the time you spend on a document in real time. Start a stopwatch when you begin working, pause it when you take a break, and stop it when you are done. The tracked time can then be submitted as a timesheet entry. The Timesheet Timer must be enabled by your administrator in **System Settings > Behavior > Enable Timesheet Timer**. ## Starting the Timer 1. Look for the **timesheet icon** in the top menu bar. 2. Hover over the icon to reveal the timer options. 3. You will see two options: - **Start Current Document** — starts tracking time for the document you are currently viewing. This option is only available when you are inside a compatible document (Project, Job, Deliverable, Client, or Contract). - **Search Document to Start** — opens a search popup so you can find and select any document to track. 4. Click one of the options to start the timer. ## Timer Running Once the timer starts, the top menu bar shows a **timer pill** displaying the elapsed time in `HH:MM:SS` format. The timer pill contains: | Element | Description | |---|---| | **Stop button** (red) | Stops the timer and opens the submission form | | **Play button** (green) | Only visible when the timer is paused — resumes the timer | | **Go-to button** | Navigates to the document being tracked | | **Time display** | Shows elapsed time. Click to pause the timer | While the timer is running, the **browser tab title** also updates to show the elapsed time and document name (e.g., `⏱ 01:23:45 - My Project`). Hover over the timer pill to see a tooltip with the document name and type. ## Pausing and Resuming - To **pause** the timer, click the time display. The time text will dim and a pause indicator will appear. - To **resume**, click the green play button that appears when paused. You can pause and resume as many times as needed. Each session segment is tracked separately. ## Stopping the Timer 1. Click the **red stop button** on the timer pill. 2. A **popup form** will open where you can review and submit the tracked time. 3. Review the tracked time, adjust if needed, and submit the entry to your timesheet. ## Switching Documents If you start a timer while another one is already running, a confirmation dialog will appear asking you to choose: - **Start New** — stops the current timer and starts a new one on the selected document. - **Continue Timer** — keeps the current timer running and dismisses the dialog. ## Overtime Alert If your timer reaches **8 hours**, the system will notify you with a browser notification and an in-app confirmation dialog. You can choose to continue tracking or stop the timer. ## Timer Persistence Your timer state is **saved automatically** on the server. If you close the browser, refresh the page, or switch devices, your timer will resume from where it left off when you log back in. ## Compatible Document Types The "Start Current Document" option is available when viewing any of the following document types: - Projects - Jobs - Deliverables - Clients - Contracts To track time on other documents, use the **Search Document to Start** option. ## Related articles - [Filling in Time Sheets](/docs/product/time/timesheets/filling-time-sheets) --- ## Transfer hours between projects or jobs URL: https://documentation.skillsworkflow.com/docs/product/time/timesheets/transferring-hours Summary: Move selected timesheet entries to another project or job. Use **Transfer Hours** to correct timesheets that were recorded against the wrong project or job. The transfer moves each selected timesheet entry in full to one destination; it does not copy the hours or split an entry between destinations. ## Before you start - You need access to the **Transfer Hours** action. If the pencil icon is not available in the Time Sheets workspace, ask your administrator to confirm that your profile has the `TransferWrite` role. - Check the dates, users and destination before saving. A transfer changes the selected entries' project or job. - The destination must be valid for the whole period of the selected timesheets. For example, if the selected entries run from 3 to 7 June, the destination project's or job's start date must be on or before 3 June and its end date must be on or after 7 June. ## Transfer the hours 1. Open the source **Project** or **Job**, then open its **Time Sheets** workspace. 2. Filter the grid to the timesheets you need to move. Filter by **Date** and **User** as needed. 3. Select the relevant timesheet rows. 4. Select the pencil icon, **Transfer Hours**. 5. In the popup, search for and select one destination. You can select either a **Project** or a **Job**. The results show the company, client, fee, project, job, and start and end dates to help you confirm the destination. 6. Select **Save**. The Time Sheets grid refreshes when the popup closes. Confirm that the selected entries now show the intended project or job. When transferring more than one timesheet, select entries that share the intended destination and whose full date range is covered by that destination. Run separate transfers when the entries need different destinations or date ranges. ## Why a destination may not appear The transfer popup only returns eligible destinations whose period covers the earliest and latest date among the timesheets you selected. If you cannot find a project or job, check its start and end dates first, then reduce the selected date range or choose a destination that covers it. ## Related articles - [Filling in Time Sheets](/docs/product/time/timesheets/filling-time-sheets) --- ## Using the Feed URL: https://documentation.skillsworkflow.com/docs/product/files-and-collaboration/feed Summary: Use the Feed to read document context, collaborate with your team, and control what client users can see. The Feed is the collaboration area for a document. It brings together the document context, messages, workflow activity, files, notifications, and conversations in one place. ## Read the document context At the top of the Feed, you can read the document description and its supporting information before reviewing the activity below. Depending on the document type and its configuration, this area can also show other descriptive fields and files attached to the document. Use this information to understand the request or brief before adding a post. The document context is separate from the Feed timeline: update the description when the document's core context changes, and use posts to record collaboration and decisions. ## Add a post or workflow action Use the composer below the document context to write a message. You can also use the available actions to add files, assign or notify people, and move the document forward in its workflow. When you publish, the Feed records the post together with the actions performed. For example, a single Feed entry can contain a message, files, a workflow-stage change, and people who were notified or mentioned. The actions available to you depend on the document, its workflow, and your permissions. ## Use Feed actions Select an action below the composer, complete the information requested, and publish the post to record the change in the Feed. The following actions were available in the current WebApp: | Action | What it does | | --- | --- | | **Move stage** | Selects an available workflow transition and moves the document to its destination stage. The transitions offered depend on the document's current stage and workflow. | | **Items** | Creates an item from the Feed. Enter its name, select its type, and set its date. The available item types depend on your configuration. | | **Add file** | Attaches a file to the post. You can also drag a file into the composer. | | **Add assignment** | Opens the document's team assignments, grouped by assignment type. Use the controls available to add, update, or remove an assignment. | | **Change end date** | Changes the document's end date and time. | | **Additional information** | Opens the additional fields configured for the document so they can be completed or updated. The fields vary by document type and configuration. | | **Notifications** | Lets you choose a user to notify when the post is published. | Do not use Notifications to include client users in an internal discussion. Notifying or `@mention`ing a client can make a post visible to that client. ## Check a person's status before you assign them Every avatar shown in **Add assignment**, and in the document's Team panel, carries a status dot for online, offline, or on leave. A user without a chat client shows as offline. Hover an avatar to open a profile card with the person's department, responsible person, email, workload, and a 14-day leave timeline. Approved leave scheduled within the next two weeks appears on that timeline. ## Deactivated users always show as inactive A deactivated user's avatar carries the inactive marker. This marker takes priority over the online, offline, and leave status. ## Follow the activity and conversations The timeline shows the most recent activity first. Each entry can include the author, time of publication, message, files, workflow activity, and notified or mentioned people. Use comments and replies on a post to keep the conversation and its context together. Use the Feed search to find previous activity when it is available in your workspace. Reactions and other post options may also be available, depending on your configuration. ## Visibility for client users A user is treated as a client when the `IsClient` flag is enabled. Whether a client can see a discussion is defined on its parent post through `IsVisibleToClient`; it is not configured separately on a comment or reply. The system determines a post's visibility automatically from the workflow: the `IsVisibleToClient` setting of the current stage or the destination stage determines whether the post is visible to clients. Comments and replies on a post that is not visible to clients are internal, because the client does not see that parent post in the normal Feed. ### Create an internal discussion To keep a discussion internal: 1. Confirm that the external user is marked as a client (`IsClient`). 2. Create the post while the document is in a workflow stage that is not visible to clients. 3. Add comments and replies to that post. 4. Do not include clients in notifications or `@mention` clients, as this can make the post visible to the client. ## Good practices - Read the description and supporting information before posting, so the conversation stays aligned with the document context. - Keep related messages, decisions, and follow-up in the same post and its replies. - Use a workflow stage that is not visible to clients before starting an internal conversation. - Check a post as an internal user: a post visible to clients displays the **Client can see** indicator. If this indicator is absent, the post is not visible to clients. ## Limitations and points of attention - A client can still see posts that they created. Do not use a post created by a client for an internal discussion. - In the current WebApp, there is no visible functional control to manually change the privacy of a post after it has been created. Set the document to the appropriate workflow stage before creating the post. - The fields, actions, and options shown in the Feed can vary by document type, workflow configuration, and user permissions. ## Related articles - [Annotations](/docs/product/files-and-collaboration/annotations) - [Create Jobs](/docs/product/projects-and-jobs/create-jobs) --- ## Using workspaces URL: https://documentation.skillsworkflow.com/docs/product/dashboards-and-reporting/using-workspaces Summary: Workspaces are the platform's own reporting and layout surface, reached at the Workspaces menu and available on most documents. # Using workspaces A workspace is a configurable view built on the platform's own data. Workspaces are reached from the **Workspaces** menu, and most documents in Skills Workflow can also carry their own workspaces alongside their Feed, Info and Files sections. The articles in this area each cover one of the workspaces that ships with the platform. ## Availability Which workspaces a person sees depends on the workspaces configured for the tenant and on that person's permissions. A document only offers workspaces if its own document type enables them. ## Related articles - [Workspaces & Reporting](/docs/product/dashboards-and-reporting) - [Client Workspace](/docs/product/dashboards-and-reporting/client-dashboard) --- ## Utilization Workspace URL: https://documentation.skillsworkflow.com/docs/product/dashboards-and-reporting/utilization-dashboard Summary: Project Managers put a lot of effort on resource allocation. Project Managers put a lot of effort on resource allocation. As much as possible, they want their team to be busy with tasks which are valuable to the agency (billable hours) as this will increase profitability. However, resource allocation becomes a challenge as the team grows when you have to assign resources to different projects all happening at the same time. One of the easiest ways to check the effectiveness of your resource allocation effort is to track and analyze your team’s utilization. Skills Workflow have developed a Utilization Workspace giving different views on how users time were spent across different dimensions. This will serve as a powerful tool to improve resource allocation. The Utilization Workspace can be accessed by selecting Workspaces from the menu bar then selecting Utilization: 1. Selection Criteria Section – Define Period, Organization Unit and User Classification by selecting from the dropdown, values for the following fields: - Year - Company - Division - Department - User Type 2. Period Selector – Provides a graph of total hours logged per day for the year selected for the set selection criteria 3. Utilization per Client – Provides a distribution in terms of percentage, hours charged per client based on the set selection criteria 4. Utilization per Department – Provides a breakdown in terms of percentage, hours charged by the different departments within the set selection criteria 5. Utilization per Project Type – Provides a breakdown in terms of percentage, hours charged to different Project Types based on the set selection criteria. 6. Utilization per User – Provides a listing of Users per Department indicating Position (Typology), Picture, Name, User Type and the following figures: - Capacity – Total Work Hours for the year less Leave Hours - Leaves – Leave hours booked for the year - Non-Billable – Hours charged to Non-Billable client tasks for the year - Admin – Hours charged to administrative tasks for the year - Billable – Hours charged to Billable client tasks for the year - Utilization Non-Billable % - (Non-Billable / Capacity) x 100 - Utilization Billable % - (Billable / Capacity) x 100 7. User Projects – By clicking a User line in the Utilization per User Listing, the system will display a breakdown of the Project/Job/Client charged by the User for the year classified according to Project Type. Details are as follows: - Non-Billable – Non-Billable hours charged by the User to Project/Job/Client - Billable – Billable hours charged by the User to Project/Job/Client - Utilization Non-Billable % - (Non-Billable / Capacity) x 100 - Utilization Billable % - (Billable / Capacity) x 100 - Hours – Total Hours per Project/Job/Client ## Related articles - [Resource Scheduler](/docs/product/planning-and-scheduling/resourcing/resource-scheduler) - [Filling in Time Sheets](/docs/product/time/timesheets/filling-time-sheets) --- ## What is a Team and what does each Group represent? URL: https://documentation.skillsworkflow.com/docs/product/people/teams/teams-and-groups Summary: The team is typically comprised by the following groups: - Each Project and Job has an assigned team - Whoever is on the team will have access to the information shared on the Project and/or Job - The team members, depending on their role, should update the job description with the brief, keynotes from meetings, e-mails exchanged with the client and upload the relevant files (e.g. last versions of the final work/output) - It is possible to define which teams have access to change the Start and End date of the Jobs. The team is typically comprised by the following groups: ## Requester The person who requests/creates the Job or Project The Accounts involved in this job ## Responsible The person who is responsible for supervising the job Typically the department heads or client responsible ## Traffic The person who assigns the creatives to each job The person who controls the workload of creatives ## Executor The person who executes the job, e.g. creatives, analytics, copywriters, strategists, etc. ## Finance Finance team who has visibility on all jobs and is usually responsible for job closing However, there is no exact definition for these groups as the team can be customized to have more or fewer groups as per the company's structure. The names can also be customized based on company needs. 1. Each group plays a different part with a different set of responsibilities 2. For each phase of the process, a person may be able to move a job forward on the workflow or not, based on the group he or she belongs to 3. Each person knows what jobs depend on his or her own actions ## Assigning an executor to a job From the Job List, select and click Job you want to assign an Executor. Click "Add Assignment" icon (People) then place the cursor beside "Executor". The pencil icon will appear then click. - A List of Resources will be displayed for selection: Choose a particular Resource then click "Submit Post" icon (Right Arrow Head) to Save. ## Related articles - [Assign or unassign users in bulk](/docs/product/people/teams/assign-users) --- ## Workspaces & Reporting URL: https://documentation.skillsworkflow.com/docs/product/dashboards-and-reporting Summary: The workspaces that ship with the platform, and what each one reports on. # Workspaces & Reporting A workspace is a reporting view built on the platform's own data. Each article here covers one workspace: what it shows, how to read it, and which part of the work it reports on — clients and projects, burn and utilization, staffing, leave, or missing time. # Start here --- ## Glossary URL: https://documentation.skillsworkflow.com/docs/start-here/glossary Summary: What each term in Skills Workflow means, how the concepts relate, and which words the interface and the API use for the same thing. The words below are used throughout this documentation, the interface and the API. A few carry more than one meaning depending on where you meet them, and a few things have one name in the interface and another in the API. Both cases are called out explicitly. Where the interface and the API disagree on a name, the entry says so under **In the API**. The interface name is the one used everywhere else in this documentation. --- ## The shape of the work These are the records the platform is built around, from the outside in. ### Client The organisation the work is for. A client can be held in two forms, which are related but not interchangeable: - **Commercial Client** — the client as the commercial teams deal with them: the brand or organisation work is delivered for. - **Billing Client** — the legal entity that is actually invoiced. One commercial client can bill through different entities in different companies. The two are linked per company, so the same brand can be commercially owned in one place and invoiced from another. In these documents, **Client** means the agency's client. **Customer** means an agency that uses Skills Workflow — you will see it in the [Trust](../trust/) section, which is written for them. If you are reading a how-to guide, the word you want is Client. ### Contract An agreement with a client that work is delivered under. Contracts can carry **Fees** — recurring or agreed amounts, such as a monthly retainer — and projects can be associated with a contract so that hours delivered are drawn down against it. ### Project A body of work for a client. A project groups the jobs that deliver it, carries its own stage, owner and dates, and can be linked to a contract. ### Job The unit of work people are actually assigned to and record time against. Jobs sit under a project. **In the API:** a Job is the `Deliverable` entity — you will see `Skill.Module.BusinessObjects.Deliverable` in webhook payloads and integration configuration. The REST endpoints, however, are `/api/jobs`. Same record, two names, depending on which layer you are looking at. Be careful with this word — it is the one term most likely to send you to the wrong page. 1. **On an Estimate**, a *Deliverable* is a line item — a service being sold to the client. See [Deliverable (Estimate line)](#deliverable-estimate-line) below. 2. **In the API and integration documentation**, `Deliverable` is the entity name for a **Job**. They are unrelated. If you are pricing something, you want sense 1. If you are reading about webhooks, stage changes or integrations, you want sense 2 — and the rest of this documentation calls that a Job. ### Request A piece of work asked for, typically raised by a client. Requests carry their own items and can become jobs. ### Brief The written description attached to a document, explaining what is wanted. A brief is attached *to* a record (a job, a project, a request) rather than being a record in its own right. **In the API:** the `DocumentBrief` entity. --- ## Money ### Estimate A priced breakdown of work, presented to the client. An estimate can be created directly under a project or job, or linked to a **Fee** on a contract. An estimate is built on its **Quotes** tab, which has four sections: | Section | What it holds | | --- | --- | | **Deliverables** | The services being sold — each line is a deliverable (see below) | | **Third Party Costs** | Costs from external suppliers | | **Expenses** | Transport, meals, hotels and similar | | **Resources** | Internal people and the hours being scoped | ### Deliverable (Estimate line) {#deliverable-estimate-line} A single line on an estimate representing something sold to the client. A deliverable can be an actual piece of work, a month of a retainer, a service, or any other way the agency wants to break the estimate down. Third party costs, expenses and resources are each quoted *against* a deliverable. This is **not** the same as a Job — see the caution under [Job](#job). ### Quote The tab on an Estimate where its detail is built, and by extension the act of pricing a line ("quote for this deliverable"). A quote is part of an estimate, not a separate document. ### Rate Card The prices and costs used when quoting resources, defined per typology group and/or per user. A rate card has columns, so the same card can carry different rates for different situations. A client can have a default rate card, which an estimate inherits. **In the interface:** the field on an Estimate that selects the rate is labelled **Table Rate**. It refers to the rate taken from the chosen Rate Card. ### Bill The document raised in Skills Workflow to charge a client. A bill is what the agency approves internally. ### Invoice The document the finance or accounting system issues from an approved bill. Most [integrations](/docs/integrations) work by sending an approved **Bill** out and writing the resulting **Invoice** reference back onto it — so a bill in Skills Workflow carries the number of the invoice it produced. ### Credit Note A document reducing an amount already invoiced, issued when the value of an invoiced estimate goes down. ### Purchase Order / Supplier Invoice **Purchase Order** — what the agency orders from a supplier. **Supplier Invoice** — what the supplier bills the agency. Both flow out to the finance system in the same way bills do. ### Expense A cost incurred by a person and reclaimed — travel, meals, and similar. Expenses are grouped into an **Expense Sheet** for approval. --- ## People and structure ### User Someone who can sign in and use Skills Workflow. ### Employee The employment record behind a person. Kept separately from the user account, so HR data can be maintained independently of platform access. **In the API:** `/api/users` and `/api/employees` are separate endpoints, and a user can be linked to an employee record. ### Typology A person's position — what they do, and therefore what they cost and what they can be scoped as. Typologies are what resources are estimated and planned against. ### Typology Group A grouping of typologies, used for rate cards, planning and reporting. Rate cards are usually defined per typology group rather than per individual typology. **Typology** is what someone does, for costing and planning. **Role** is what someone is allowed to see and do in the platform. Changing a typology affects rates and resourcing; changing a role affects permissions. ### Role An access profile controlling what a user can see and do. Roles govern permissions — including, in places, which individual columns of a document are visible. ### Company, Division, Department The organisational hierarchy, from largest to smallest. A **Company** is a legal entity with its own settings, currency and finance connection. A **Division** groups departments within it. A **Department** is where people sit, and is used for planning and workflow. A single Skills Workflow tenant can hold several companies, each with its own configuration and its own integration credentials. --- ## Workflow ### Stage Where a document currently sits in its process — for example a bill that is Under Approval, or a job that is In Progress. Every document type has its own set of stages. **In the API:** a stage is a `workflowState` — you will see it as `workflowState` in payloads and `/api/jobs/{id}/workflowstate` as an endpoint. "Stage" and "workflow state" are the same thing. This documentation uses **Stage** for where a document is in its workflow. Where you see **status**, it usually means something else — for instance whether an integration run succeeded. If a page uses "status" to mean the workflow stage, read it as Stage. ### Transition The move from one stage to the next, and the permission to make it. A transition has to exist between two stages for a document to move between them — which is why an [integration](/docs/integrations) may report that it could not apply a stage change even though the target stage exists. ### Workflow The full set of stages and transitions for a document type, including who may make each move and what happens when they do. ### Workflow Action Something the platform performs automatically as part of a transition — creating a version, assigning someone, requesting confirmation, sending an e-mail, generating an estimate, and so on. --- ## Automation and integration ### Automation A configured sequence of steps the platform runs on its own — calling an external system, running a query, creating or updating records. Most [integrations](/docs/integrations) are built from automations. ### Webhook A trigger that fires when something happens to a document — created, updated, stage changed, deleted — and starts an automation. Webhooks can be filtered, so they only fire for particular stages or document types. ### Named Query A saved query used by automations and workspaces to look up or assemble data. ### Workspace A configurable screen — a dashboard or a panel on a record — built from components and data sources. Some integrations ship workspaces that embed an external system directly into a record. ### System Parameter / Configuration Key Where connection settings and credentials for an integration are stored, kept out of the automation itself so they can differ per environment. ### Custom Field An additional field added to a document type beyond the standard ones. Integrations commonly use a custom field to store the matching record's identifier in the external system. ### Custom Table A table of data held in Skills Workflow outside the standard model — used for reference data, and by some integrations for their own bookkeeping. --- ## Time ### Timesheet A record of time worked, entered against a job by a user, and approved. ### Leave Time off — holiday, sickness and similar. Leave is what makes someone unavailable in resourcing and scheduling, which is why [HR integrations](/docs/integrations) exist to keep it current. ### Typology-based planning Scoping work by **typology** rather than by named person, so a plan can be built before it is known who will do it. ### FTE Full-Time Equivalent — a unit expressing workload as a proportion of a full-time person. ### Utilisation How much of someone's available time is spent on billable work. ### Burn How much of an estimated or contracted amount has been consumed by actual hours. --- ## Releases URL: https://documentation.skillsworkflow.com/docs/start-here/releases Summary: Every change shipped in Skills Workflow, grouped by version — improvements, change requests and fixes. # Releases Everything shipped in Skills Workflow, newest version first. Use the filters to narrow to improvements, change requests or fixes, or search across every entry. The list is refreshed each time the documentation is deployed.