Skip to main content
Wildo.ai Coming soon

Events and external data

Use external records where your application needs them

Read and change records in the system that holds them, or keep a local copy current in either direction, according to how the application needs to use them.

External records can be read directly or synchronized into a local copy with application-owned notes.

Use external records where your application needs them

Data can remain in its original system, where your application reads it when needed and, where you allow it, changes it. Or it can become a synchronized part of your application, copied in, sent out or kept in step on both sides. Wildo supports each choice through resource declarations.

Read-through suits remote reference data and records people correct in passing. A local copy lets your application add its own fields, attachments and relationships, with freshness determined by the synchronization schedule.

Example — Keep customer accounts and local notes together

An application copies company accounts from Odoo, then lets its users add internal notes. A later synchronization updates the mapped account fields while the application retains the fields it owns.

For engineers

A virtual resource uses persistenceAdapter: HTTP_API with httpApiBinding. Its repository translates supported reads to the external system and sends single-record creates, updates and deletes for the verbs the binding opens; it has no local row for extra fields or files. A pipeline declaration belongs to an ordinary local resource and populates that resource through the data-seeding engines, or, declared outbound or two-way, sends its rows to the external system.

Both use HttpApiReadClient for access, dialect framing and remote calls. A binding names the system of record it reads, declared once under systemsOfRecord in wildo.saas.config.ts, and declares the remote entity and key mapping, which are required semantic decisions, not optional labels. Who answers for the records’ personal data defaults to the system of record and is declared only when it differs. A system of record belongs to one owner organization, and its rows are stamped with that organization’s id; on an instance declared partitioned, they are further confined to the organization units each remote company is assigned to.

This pipeline block is selected from Wonder Todos’ external-customers.resources-config.ts; its partition fields, source comments, and the surrounding resource factory and operation declarations are omitted:

  externalDataPipeline: {
    binding: {
      dialect: HttpApiTransportDialect.ODOO_JSONRPC,
      system: 'odoo',
      entityRef: 'res.partner',
      keyFields: [{ localField: 'id', remoteField: 'id', codec: HttpApiKeyComponentCodec.INTEGER }],
      subjectRights: { posture: SystemOfRecordSubjectRightsPosture.HANDLED_AT_SOURCE },
      purposeRefs: ['task-planning-service'],
    },
    remoteKeyLocalField: 'odooPartnerRef',
    mapping: [
      {
        kind: ExternalDataMappingEntryKind.CONCATENATION,
        localField: 'name',
        parts: [
          { kind: ExternalDataConcatenationPartKind.REMOTE_FIELD, remoteField: 'name' },
          { kind: ExternalDataConcatenationPartKind.REMOTE_FIELD, remoteField: 'ref' },
        ],
        separator: ' · ',
      },
      { kind: ExternalDataMappingEntryKind.REMOTE_FIELD, remoteField: 'email', localField: 'email' },
    ],
    sourceFilter: { is_company: true },
    population: ExternalDataDestinationPopulation.CLOSED,
    orphanPolicy: ExternalDataOrphanPolicy.IMPERSONALIZE,
    scheduleCron: '0 * * * *',
  },

The closed population means the source supplies the records: this resource declares no caller create operation. Its local internalNote is editable, while imported fields exclude create/update input in the schema. The mapping owns only its declared fields, one of them built by a declared expression from two remote fields. The subject-rights posture says Odoo, which the application only reads, answers requests about its own client records, so an erasure that reaches these rows completes and its receipt names Odoo. A client that no longer appears in a complete pass has its copied name and email, and its note, scrubbed in place (IMPERSONALIZE), and the row is kept. Register the schema, resource factory and relationships through the shared module, and supply the system of record’s address and credential for each environment.

Treat synchronization as a population contract

remoteKeyLocalField holds a stable identity derived from the external binding. An extraction that reaches the source’s end selects sync reconciliation; a bounded pass selects upgrade reconciliation and persists its continuation. A persisted membership journal keeps the identities each run of a pass observed, so the final comparison covers the whole pass rather than only the last run’s rows.

RequirementSuitable lane
Read the external response on demandVirtual read-through
Change a record where it livesVirtual read-through with opened write verbs
Add local notes or filesLocal pipeline destination
Avoid remote latency on ordinary readsLocal pipeline destination
Send records the application createsOutbound pipeline
Let both sides edit one recordTwo-way pipeline, with each field’s owner declared
Keep no duplicated rowVirtual read-through

Start with REPORT until the population and its filter are understood: automatic orphan deletion acts on what a completed pass did not see, and a filter or permission change at the source can make records vanish from view without being deleted. A completed extraction is not a claim that every row passed transformation; inspect rejections and reconciliation results. Do not declare NO_SUBJECT_DATA for a source containing people’s information: the factory refuses it beside any mapped field whose declared category describes a person.

Building a B2B product or an internal tool?

Wildo is not self-service yet. Tell us what you have in mind and we will say plainly whether it fits, and what happens next.