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

# Entity Matcher

> Establishing the initial mapping between local and remote entities

export const Shot = ({id, caption}) => {
  const screenshots = {
    "domain-mappings.sync-trigger-actions-employee": {
      path: "images/backoffice/configuration/domain-mappings/sync-trigger-actions-employee.png",
      caption: "Each sync trigger exposes action buttons for an ad-hoc sync and for editing the trigger configuration.",
      w: 2880,
      h: 1800,
      highlights: [{
        key: "sync-now",
        description: "Fires an immediate one-off sync without waiting for the next scheduled run. Handy when you want to see the effect of a configuration change right away.",
        x: 0.8854,
        y: 0.5056,
        w: 0.025,
        h: 0.0511
      }, {
        key: "edit",
        description: "Opens the edit modal where the schedule, parent trigger, scheduled toggles, and any domain-specific settings for this trigger can be adjusted.",
        x: 0.916,
        y: 0.5056,
        w: 0.025,
        h: 0.04
      }]
    },
    "domain-mappings.sync-trigger-edit-employee": {
      path: "images/backoffice/configuration/domain-mappings/sync-trigger-edit-employee.png",
      caption: "The Edit Sync Trigger modal for a non-time-report mapping.",
      w: 900,
      h: 1124,
      highlights: [{
        key: "cron-enabled",
        description: "Controls whether the trigger fires automatically. When it is turned off, the trigger only runs if someone starts it manually.",
        x: 0.0556,
        y: 0.3149,
        w: 0.2336,
        h: 0.0783
      }, {
        key: "cron-expression",
        description: "Standard cron syntax that determines when the trigger runs while the schedule is enabled.",
        x: 0.3247,
        y: 0.3149,
        w: 0.6198,
        h: 0.1103
      }, {
        key: "scheduled-toggles",
        description: "Queues future flips of the enable state. Useful for pausing a trigger during a maintenance window and having it re-enable itself afterwards without manual intervention.",
        x: 0.0556,
        y: 0.468,
        w: 0.8889,
        h: 0.2349
      }, {
        key: "parent-trigger",
        description: "Chains this trigger to run immediately after another one completes, so dependent syncs always happen in the right order.",
        x: 0.0556,
        y: 0.7456,
        w: 0.8889,
        h: 0.1032
      }]
    },
    "domain-mappings.sync-trigger-actions-time-report": {
      path: "images/backoffice/configuration/domain-mappings/sync-trigger-actions-time-report.png",
      caption: "Time-report mappings expose the same sync trigger actions as other domains.",
      w: 2880,
      h: 1800,
      highlights: [{
        key: "sync-now",
        description: "Fires an immediate sync. On time-report mappings this first opens a small dialog for picking the date range to pull before the sync actually runs.",
        x: 0.8854,
        y: 0.5056,
        w: 0.025,
        h: 0.0511
      }, {
        key: "edit",
        description: "Opens the edit modal. For a time-report mapping this exposes an extra section for the default date range the scheduled sync should cover.",
        x: 0.916,
        y: 0.5056,
        w: 0.025,
        h: 0.04
      }]
    },
    "domain-mappings.sync-trigger-edit-time-report": {
      path: "images/backoffice/configuration/domain-mappings/sync-trigger-edit-time-report.png",
      caption: "The Edit Sync Trigger modal for a time-report mapping exposes an extra date-range section.",
      w: 900,
      h: 1388,
      highlights: [{
        key: "cron-enabled",
        description: "Controls whether the trigger fires automatically. When it is turned off, the trigger only runs if someone starts it manually.",
        x: 0.0556,
        y: 0.255,
        w: 0.2336,
        h: 0.0634
      }, {
        key: "cron-expression",
        description: "Standard cron syntax that determines when the trigger runs while the schedule is enabled.",
        x: 0.3247,
        y: 0.255,
        w: 0.6198,
        h: 0.0893
      }, {
        key: "scheduled-toggles",
        description: "Queues future flips of the enable state. Useful for pausing a trigger during a maintenance window and having it re-enable itself afterwards without manual intervention.",
        x: 0.0556,
        y: 0.379,
        w: 0.8889,
        h: 0.1902
      }, {
        key: "parent-trigger",
        description: "Chains this trigger to run immediately after another one completes, so dependent syncs always happen in the right order.",
        x: 0.0556,
        y: 0.6037,
        w: 0.8889,
        h: 0.0836
      }, {
        key: "time-report-settings",
        description: "Defines which date range the sync should pull time reports for. The start and end dates can each be either a fixed date or a dynamic expression evaluated at run time.",
        x: 0.0556,
        y: 0.7219,
        w: 0.8889,
        h: 0.1556
      }]
    },
    "domain-mappings.employee-outgoing": {
      path: "images/backoffice/configuration/domain-mappings/employee-outgoing.png",
      caption: "An outgoing Employee → Employee mapping pushes Twine employee data into a target system.",
      w: 2880,
      h: 1800
    },
    "domain-mappings.time-report": {
      path: "images/backoffice/configuration/domain-mappings/time-report.png",
      caption: "Time report mappings include a dedicated time-code mapping section alongside the standard configuration.",
      w: 2880,
      h: 1800,
      highlights: [{
        key: "time-code-mapping",
        description: "Appears only on time report to time report mappings. Lines up each time code in the source system with the matching Twine time code so reported hours land in the right bucket downstream.",
        x: 0.1778,
        y: 0.4256,
        w: 0.4,
        h: 0.5567
      }]
    },
    "jobs.details": {
      path: "images/backoffice/daily-operations/jobs/details.png",
      caption: "The Job Details page shows everything about a single sync job — its metadata, status, descendants, and streaming logs.",
      w: 2880,
      h: 1800
    },
    "system-integration-settings.authentication": {
      path: "images/backoffice/configuration/system-integration-settings/authentication.png",
      caption: "The Authentication sub-tab holds credentials and a sharable authentication URL generator.",
      w: 2880,
      h: 1800,
      highlights: [{
        key: "generate-url-button",
        description: "Generates a one-time shareable URL that lets a customer without a Twine login enter their own credentials. The link stays valid for five days.",
        x: 0.816,
        y: 0.3378,
        w: 0.1555,
        h: 0.04
      }]
    },
    "system-integration-settings.authentication-url-generated": {
      path: "images/backoffice/configuration/system-integration-settings/authentication-url-generated.png",
      caption: "After clicking Generate Authentication URL, the card displays the shareable link with a copy button.",
      w: 872,
      h: 948,
      highlights: [{
        key: "copy-button",
        description: "Copies the generated link to the clipboard so it can be pasted into an email or chat to the customer.",
        x: 0.8945,
        y: 0.692,
        w: 0.0275,
        h: 0.0253
      }]
    },
    "system-integration-settings.general": {
      path: "images/backoffice/configuration/system-integration-settings/general.png",
      caption: "The General sub-tab holds system-specific settings that are not credentials.",
      w: 2880,
      h: 1800,
      highlights: [{
        key: "system-specific-card",
        description: "Holds configuration that is specific to the connected system and unrelated to authentication. The exact fields depend on which integration is selected.",
        x: 0.6861,
        y: 0.2633,
        w: 0.3028,
        h: 0.28
      }]
    },
    "system-integration-settings.time-reports": {
      path: "images/backoffice/configuration/system-integration-settings/time-reports.png",
      caption: "The Time Reports & Types sub-tab configures how source time codes map to Twine time codes.",
      w: 2880,
      h: 1800,
      highlights: [{
        key: "refresh-button",
        description: "Re-fetches the current time-type catalogue from the connected system so the mapping list picks up anything that has been added or removed upstream.",
        x: 0.3896,
        y: 0.9144,
        w: 0.1529,
        h: 0.04
      }]
    },
    "system-integrations.admin": {
      path: "images/backoffice/configuration/system-integrations/admin.png",
      caption: "The Admin tab exposes destructive and one-shot administrative actions for a system integration.",
      w: 2880,
      h: 1800
    },
    "system-integrations.domains-overview": {
      path: "images/backoffice/configuration/system-integrations/domains-overview.png",
      caption: "The Domains tab lists outgoing and incoming domain mappings for this system integration.",
      w: 2880,
      h: 1800,
      highlights: [{
        key: "create-button",
        description: "Opens a dialog where you pick the direction, target integration, and source and target domains for a new mapping.",
        x: 0.8297,
        y: 0.2633,
        w: 0.1592,
        h: 0.04
      }]
    },
    "system-integrations.domains-create-dialog": {
      path: "images/backoffice/configuration/system-integrations/domains-create-dialog.png",
      caption: "The Create Domain Mapping dialog starts with the direction radio and an empty form.",
      w: 900,
      h: 964
    },
    "system-integrations.domains-create-dialog-filled": {
      path: "images/backoffice/configuration/system-integrations/domains-create-dialog-filled.png",
      caption: "Once a target system integration and source/target domains are selected, the Create button unlocks.",
      w: 900,
      h: 964
    },
    "anomalies.list": {
      path: "images/backoffice/daily-operations/anomalies/list.png",
      caption: "The Anomalies page lists issues grouped by severity, system, and status.",
      w: 2880,
      h: 1800
    },
    "entity-matcher.integration-overview": {
      path: "images/backoffice/configuration/entity-matcher/integration-overview.png",
      caption: "The Entity Matcher is accessed from the overview page of a System Integration.",
      w: 2880,
      h: 1800
    },
    "entity-matcher.filter-form": {
      path: "images/backoffice/configuration/entity-matcher/filter-form.png",
      caption: "Select a domain and match field before searching for entity matches.",
      w: 1536,
      h: 300
    },
    "entity-matcher.search-results": {
      path: "images/backoffice/configuration/entity-matcher/search-results.png",
      caption: "Local entities on the left, remote candidate entities in the dropdowns on the right.",
      w: 1536,
      h: 800
    },
    "integrations.alexis_hr.system-settings": {
      path: "images/integrations/screenshots/alexis_hr/system-settings.png",
      caption: "The system-specific settings tab for Alexis HR on its configured integration.",
      w: 2880,
      h: 1800
    },
    "jobs.list": {
      path: "images/backoffice/daily-operations/jobs/list.png",
      caption: "The Jobs page shows sync jobs with their type, domain, status, and creation time.",
      w: 2880,
      h: 1800
    },
    "notifications.settings": {
      path: "images/backoffice/configuration/notifications/settings.png",
      caption: "Notification settings control which events trigger alerts and who receives them.",
      w: 2880,
      h: 1800
    },
    "roles.list": {
      path: "images/backoffice/configuration/roles/list.png",
      caption: "The Roles page lets you define roles and the rules that govern access within an organization.",
      w: 2880,
      h: 1800
    },
    "roles.quick-start-wizard": {
      path: "images/backoffice/configuration/roles/quick-start-wizard.png",
      caption: "The Quick start wizard creates a preconfigured Org admin or Org user role in one step.",
      w: 1060,
      h: 928
    },
    "roles.detail-sheet": {
      path: "images/backoffice/configuration/roles/detail-sheet.png",
      caption: "Clicking a role opens a detail sheet showing metadata, tokens, and a link to manage rules.",
      w: 2880,
      h: 1800
    },
    "roles.rules-page": {
      path: "images/backoffice/configuration/roles/rules-page.png",
      caption: "The rules page shows all rules for a role. Expanding a rule reveals its TERLs.",
      w: 2880,
      h: 1800
    },
    "roles.edit-rule": {
      path: "images/backoffice/configuration/roles/edit-rule.png",
      caption: "The rule editor lets you configure a rule name, policy, actions, and TERLs.",
      w: 1344,
      h: 1232
    },
    "roles.tokens-add-form": {
      path: "images/backoffice/configuration/roles/tokens-add-form.png",
      caption: "Add a new API or refresh token to a role by filling in the name and type.",
      w: 1344,
      h: 1800
    },
    "roles.token-created": {
      path: "images/backoffice/configuration/roles/token-created.png",
      caption: "After creating a token, copy it immediately — it is only shown once.",
      w: 1344,
      h: 1800
    },
    "roles.tokens-list": {
      path: "images/backoffice/configuration/roles/tokens-list.png",
      caption: "The Tokens table shows every active API and refresh token for the role.",
      w: 1344,
      h: 1800
    },
    "roles.token-revoked": {
      path: "images/backoffice/configuration/roles/token-revoked.png",
      caption: "Revoking a token immediately invalidates it. Revoked tokens disappear from the list.",
      w: 1344,
      h: 1800
    },
    "roles.add-terl": {
      path: "images/backoffice/configuration/roles/add-terl.png",
      caption: "Click \"Add new TERL\" to add a resource target to a rule.",
      w: 1344,
      h: 1536
    },
    "system-data.employee-detail": {
      path: "images/backoffice/data/system-data/employee-detail.png",
      caption: "Selecting an employee opens a detail view with properties, metadata, and source data inspection tools.",
      w: 2880,
      h: 1800
    },
    "system-data.time-reports-employee": {
      path: "images/backoffice/data/system-data/time-reports-employee.png",
      caption: "Filter time reports by employee and date range to see reported time across a specific period.",
      w: 2880,
      h: 1800
    },
    "system-data.employees-list": {
      path: "images/backoffice/data/system-data/employees-list.png",
      caption: "The Employees table shows every employee ingested from the connected source systems.",
      w: 2880,
      h: 1800
    },
    "system-data.time-reports": {
      path: "images/backoffice/data/system-data/time-reports.png",
      caption: "Time Reports displays a calendar-style grid of reported time, grouped by employee or time code.",
      w: 2880,
      h: 1800
    },
    "system-integration-settings.metadata": {
      path: "images/backoffice/configuration/system-integration-settings/metadata.png",
      caption: "The Metadata sub-tab shows system-specific metadata fetched from the source system.",
      w: 2880,
      h: 1800
    },
    "templates.list": {
      path: "images/backoffice/configuration/templates/list.png",
      caption: "Mapping Templates define how data from a source system is mapped into Twine.",
      w: 2880,
      h: 1800
    }
  };
  const shot = screenshots[id];
  if (!shot) return <div style={{
    color: '#dc2626',
    padding: '12px',
    border: '1px solid #dc2626',
    borderRadius: '6px',
    fontSize: '13px',
    margin: '24px 0'
  }}>
      Screenshot not found: <code>{id}</code>
    </div>;
  const displayCaption = caption || shot.caption;
  return <figure style={{
    margin: '24px 0'
  }}>
      <img src={`/${shot.path}`} alt={displayCaption || ''} style={{
    width: '100%',
    height: 'auto',
    borderRadius: '8px',
    border: '1px solid rgb(var(--primary-light) / .15)',
    boxShadow: '0 1px 3px rgb(0 0 0 / .06)',
    display: 'block'
  }} />
      {displayCaption && <figcaption style={{
    marginTop: '8px',
    fontSize: '13px',
    color: 'var(--colors-content-secondary, #6b7280)',
    textAlign: 'center',
    fontStyle: 'italic'
  }}>
          {displayCaption}
        </figcaption>}
    </figure>;
};

The **Entity Matcher** is a backoffice tool used to establish the initial mapping between entities stored in Twine and the corresponding records in a connected system. It is opened from a [System Integration](/platform/system-integrations)'s overview page.

<Shot id="entity-matcher.integration-overview" />

## Selecting a domain and match field

After opening the matcher, select a **domain** and a **match field** - a field on that domain whose value is used to find candidate remote entities. The match field is only used for the initial search; once a mapping is saved, the stored mapping almost always references the remote system's database ID rather than the match field value.

<Shot id="entity-matcher.filter-form" />

## Reviewing matches

The matcher shows all local entities on the left, paired with a dropdown on the right that lists candidate remote entities. The bidirectional arrow between them indicates the match status:

* **Arrow with default background** - an existing, saved mapping. This entity is already matched.
* **Arrow with orange background** - a suggested match based on the match field. The suggestion should be reviewed before saving.
* **Transparent arrow** - no match could be determined. The dropdown can be searched manually to find the correct remote entity.

Rows without a candidate match can be filled in manually by searching the dropdown. Incorrect prepopulated suggestions can be changed the same way.

<Shot id="entity-matcher.search-results" />

### Ignoring entities

The checkbox next to each entity's description controls whether that row is included when saving. Unchecking it means the entity is completely ignored - no mapping is created or changed for it, even if a match is shown. This is useful for excluding entities that should not be mapped to the target system.

## Saving

Saving the matcher persists the resulting [EmployeeMappings](/platform/other/employee-mapping) (or the equivalent for other entity types) for the selected System Integration. Only rows with the checkbox enabled are affected. Once saved, subsequent changes to the match field do not affect existing mappings - they are anchored to the remote database ID.
