Scoping · v1.0 — mapping signed off 17 Jul 2026

Hyperline → Upflow connector

Scoping & mapping document · first merchant: Kolsquare

Sources: Hyperline live full scans on the Kolsquare production read-only key (16–17 Jul 2026: 3,046 customers · 3,507 invoice records) + docs.hyperline.co · Upflow OpenAPI 3.1.1 + sandbox tests + public integration guide · Upflow-side decisions confirmed in writing (Sarah-Nicole, 17 Jul 2026).

PLATFORM — reusable across merchants KOLSQUARE — merchant-specific OPEN — pending decision

1. Overview

  • What: one-way sync, Hyperline (billing) → Upflow (A/R). Dedicated Node.js service, built multi-merchant from day one.
  • Hosting & operations: Reviaflow infrastructure (EU), per the agreement of 15 Jul 2026. Handover-ready codebase for a possible future re-hosting on Upflow infrastructure.
  • Creation ownership (settled, 17 Jul): the connector creates customers and contacts. Upflow's Salesforce connection is optional, secondary enrichment, out of connector scope (see § 13).
  • Org topology (settled, 17 Jul): three separate Upflow organizations, one per Hyperline invoicing entity (Kolsquare · Kolsquare Italy · Storyclash GmbH). One API key pair per org; custom-field definitions provisioned in each org.
  • Amounts: minor units (cents) on both sides. No conversion.

2. Architecture & sync model

ComponentBehaviourLayer
RuntimeAlways-on Node.js service, isolated environment on EU infrastructure, secrets in encrypted store, deploy pipeline, monitoring.PLATFORM
Incremental syncHourly poll on Hyperline updated_at cursor (payment recording bumps it — verified on 2,389 paid invoices, zero counter-example).PLATFORM
Pre-dunning runDedicated run every morning before Upflow's dunning scheduler, so an invoice recorded as paid in Hyperline is never dunned.PLATFORM
Nightly sweepConsistency pass: open invoices cross-checked on both sides; detects records deleted in Hyperline (invisible to incremental polling) and removes them from Upflow.PLATFORM
IdempotenceEvery write is an upsert on externalId. Re-running a sync never duplicates. Safe recovery = re-run.PLATFORM
Dry-run modeFull run with zero writes, complete diff output. Reviewed together before any production write.PLATFORM
Org routingEvery customer and its attached objects routed by invoicing_entity_id to the matching Upflow org (×3).KOLSQUARE config on a PLATFORM mechanism
Initial importAll open invoices regardless of age + ~1 year of settled history. Any open invoice carries its complete payment & credit chain even beyond 1 year (outstanding amounts must match Hyperline exactly). Runs in Test Mode.KOLSQUARE
WebhooksNot in v1 (see § 11). Polling is the backbone: Hyperline webhooks carry no partial payments and no delivery/order guarantee. HTTPS endpoint reserved at infra level for a later real-time layer.PLATFORM (v2 option)
Freshness boundary. The connector mirrors what Hyperline has recorded. A payment enters Upflow when Hyperline records it (reconciliation, merchant-side): on measured Kolsquare data, recording lags the bank settlement by ~1.6 days median. A reminder sent inside that window is a reconciliation-cadence matter, not a sync failure.

3. Object-level map

#Hyperline object→ Upflow objectWrite pathIdempotence keyKolsquare volume
1Customer (native)Customer (native)POST /customers (upsert)externalId = Hyperline customer id (cus_…)all invoiced-in-scope
2— (no contact entity; emails on customer)Contact (native, sub-resource)POST /customers/{ref}/contactshyp:{cus_id}:{email} (synthetic)~1,961 projected
3Invoice (type=="invoice")Invoice (native)POST /invoices (upsert)externalId = inv_… · customId = trimmed number3,230 · 589 open
4Transaction (embedded in invoice)Payment (native)POST /payments + allocationexternalId = tra_…2,506 settled
5Credit note (type=="credit_note")Credit Note (native)POST /credit_notes + allocationexternalId = Hyperline id277 (274 linked)
6Invoice PDF (authenticated download)Invoice PDF (Upload API)POST /invoices/external:{id}/pdfinvoice externalId1 per synced invoice
7Refund signal (refunded_at)Refund (native)not fed in v1 — see § 90 money-out refunds
Key design fact. Upflow invoice state and amountOutstanding are not writable. An invoice becomes PAID only through payment / credit-note allocations covering its amount. The payments flow is therefore the mechanical carrier of invoice status — reconciliation itself stays in Hyperline.
Org constraint. POST /payments is rejected on an Upflow org connected to a native billing integration. The three Kolsquare orgs must remain API-fed only (this connector is the feed).

4. Customers

  • Creation ownership: the connector creates customers (Hyperline = source of truth for customer creation, per Upflow's written guidance, 17 Jul).
  • Inclusion rule: a customer is created in Upflow iff it owns ≥1 invoice inside the import scope. Ongoing: a customer enters at its first finalized (non-draft) invoice. Never-invoiced customers never enter (773 no-invoice records excluded as noise).
Hyperline field→ Upflow fieldNotes
id (cus_…)externalIdThe matching key (settled 17 Jul): 100% coverage, unique, immutable, single creator.
namenameDirect.
billing_address {…}address {…}Field-by-field mapping.
vat_numbervatNumberDirect.
billing_email, invoice_emails[]→ Contact flow (§ 5)Emails live only on contacts in Upflow.
Salesforce link (integrations[].entity_id)Custom field salesforce_account_idCarried where present. Not the matching key (§ 13). Feeds the SF-link coverage report.
invoicing_entity_idorg routing (×3)Drives which Upflow org receives the customer and all attached objects.
status, deleted_atsync filterOnly active customers in scope; archived/deleted → surfaced in the run report.
currency, language, timezone, subscriptions, payment methods, price book, segments, domain, tax idsnot mappedBilling-engine internals, no A/R equivalent.

Upflow native fields not fed by this connector: accountManagerId, assignedUsers, dunningPlanId (Upflow configuration), parent, paymentMethods, accountingRef.

5. Contacts

Structural facts. Hyperline has no contact entity; the Upflow customer has no email field. Contacts are derived from the two Hyperline email fields and are the sole channel carrying dunning recipients into Upflow. Hyperline's own routing rule: invoices go to invoice_emails[] when set; billing_email is the fallback only. The email snapshot embedded in invoices (invoice.customer.email) is frozen at emission and is never read.
  • Derivation: per synced customer, deduplicated union (trim + lowercase) of billing_email + invoice_emails[] → one Upflow contact per email, create-if-absent.
  • Primary recipient (isMain): first invoice_emails[] entry when the list is set, else billing_email — faithful to Hyperline routing.
  • No name fabrication: first/last names left empty. Person names may come later from Salesforce enrichment (out of scope).
  • Ownership boundary: the connector only ever touches contacts with the hyp: externalId prefix. A billing box removed in Hyperline gets its hyp: contact removed; contacts from any other source (manual, Salesforce) are never touched.
  • Duplicate-email safety: settled in writing (17 Jul): Upflow sends each email only once even with duplicated contacts — no double-dunning risk.

Source configurations (invoiced cohort, n = 1,429, drafts excluded):

ConfigurationVolumeContacts createdPrimary
billing_email only555 (39%)1billing_email
invoice_emails only229 (16%)1 per list entryfirst list entry
both set628 (44%)deduplicated unionfirst invoice_emails entry; billing_email becomes secondary
≥2 invoice_emails (subset)328 (23%)1 per boxfirst list entry (deterministic projection of Hyperline's send-to-all)
no email at all17 (1%)none — flagged in quality report— (customer still created)
Guard. The connector never uses the contacts field of the customer import: that path has documented full-replace semantics (any omitted contact is deleted) and would destroy contacts created by other writers. Only the per-contact sub-resource endpoint is used.

Dunning recipient policy (OPEN — Upflow onboarding decision, not connector behaviour): "all contacts" is the only policy reproducing Hyperline's multi-box sending (328 customers have ≥2 recipient boxes); "main only" under-sends for those. Every contact the connector creates is a billing box by construction. Data provided; decision owned by Upflow/Kolsquare at onboarding.

6. Invoices

Hyperline field→ Upflow fieldNotes
id (inv_…)externalIdStable upsert key.
numbercustomIdTrimmed (leading space present in the API payload). Human cross-system key.
emitted_at / due_atissuedAt / dueDateUpflow derives DUE vs OVERDUE.
currency, total_amount, amount_excluding_taxcurrency, grossAmount, netAmountCents → cents, currency as-is (no conversion).
customer.idcustomer: {externalId}Same pivot key as § 4.
status, amount_due, amount_paidnever pushedUpflow state is derived from allocations (§ 3 key fact). Used for run reports and consistency checks only.
reference / purchase_order / service period / public_urlcustom fields (final list at build)Upflow purchaseOrder is not API-writable → custom field.
PDF binaryPOST …/pdfAuthenticated download → upload relay. Re-pushed on every touched invoice (last-write-wins).
tax details, discounts, FX fields, line items, subscription/payment-method/bank refsnot mappedNo A/R equivalent.

Status handling:

Hyperline statusCountConnector behaviour
draft12Never synced.
to_pay574Pushed; Upflow derives DUE/OVERDUE.
partially_paid15Pushed + partial allocations → correct outstanding in reminders.
paid2,642Pushed + full allocations (backfill: ~1 year of settled history per agreed scope).
voided263Skipped at backfill together with the voiding credit note (each voided invoice has exactly one). Voided after sync: deleted from Upflow with its credit note and payments in the same run ("full cancellation", settled 17 Jul).
uncollectible1OPEN Upflow WRITTEN_OFF not API-writable → surfaced in the quality report for manual write-off in the Upflow UI (Upflow/merchant action).
error1Excluded + surfaced in quality report.

7. Payments

Only status == "settled" transactions become payments (2,506 of 2,526; failed 15 / scheduled 5 ignored).

Hyperline (transaction)→ Upflow (payment)Notes
id (tra_…)externalId + refNumberMachine upsert key + human-visible reference.
amount, currencyamount, currencyCents → cents.
settled_atvalidatedAtDay-granularity in Hyperline (measured); reflects bank date, recording arrives at reconciliation.
payment_method_typeinstrumenttransfer (2,022) → WIRE_TRANSFER · direct_debit (21) → DIRECT_DEBIT · external (483) → OPEN UNKNOWN vs WIRE_TRANSFER, awaiting Kolsquare.
parent invoicelinkedInvoices[] allocationThe allocation is what flips invoice status.
statusstate: VALIDATED
Edge case (measured: 4 invoices). Manually marked-as-paid invoices carry no transaction at all. The invoice status is authoritative: the connector generates a synthetic payment (official Upflow pattern: amount = invoice amount, date = issue date) and flags it in the quality report.

8. Credit notes

Hyperline stores credit notes in the same collection as invoices (type == "credit_note", amounts positive, 274/277 linked to an origin invoice). Upflow has a dedicated collection.

Field mapping mirrors invoices (externalId, trimmed number → customId, cents, customer pivot, original_invoice_idlinkedInvoices[] allocation, PDF relay). Sync rule by origin-invoice status (measured; no invoice carries more than one credit note):

Origin invoice statusCountRule
voided263Skip the pair — pure annulation, no A/R value (consistent with § 6).
open (to_pay / partially_paid)4v1-critical: push + allocate. The credit reduces the outstanding; without it Upflow over-dunns.
paid / uncollectible7Pushed within history scope. OPEN build detail: allocate vs leave as unapplied customer credit.
no origin invoice3Quality report.

9. Refunds

  • Measured (16 Jul): all 175 invoices carrying refunded_at are targets of a credit note; zero transactions were ever refunded. In Hyperline as Kolsquare uses it, "refunding" = issuing a credit note (accounting reversal), not money sent back.
  • Consequence: the substance is fully carried by the credit-note flow (§ 8). Upflow's /refunds collection has nothing to carry → not fed in v1.
  • Guard: if a sync run ever encounters a refunded transaction → fail-loud alert + manual review; the refunds mapping gets wired then, against real cases.

10. Data quality & run reporting

Every run produces a report. Exclusions and anomalies are always surfaced, never silent:

  • Customers with zero email (17 today) — customer still created, flagged.
  • Salesforce-link coverage (informational): invoiced customers without a SF link (~120), duplicated SF Account IDs (28).
  • Invoices in error (1) / uncollectible (1).
  • Credit notes without an origin invoice (3).
  • Synthetic payments generated for marked-as-paid invoices (4 today).
  • Customers on an unknown invoicing entity (0 expected — hard flag).
  • Any refunded transaction (0 expected — hard alert).
  • Records deleted in Hyperline detected by the nightly sweep.
  • Invoices whose PDF could not be retrieved from Hyperline — the invoice data still syncs, the PDF is retried and the failure is flagged.

11. Scope: in / out

IN SCOPE — v1

  • Customers, contacts, invoices, invoice & credit-note PDFs, payments, credit notes (as specified §§ 4–8)
  • Routing to 3 Upflow orgs by invoicing entity
  • Initial import (open all-age + ~1 year settled + complete chains on open)
  • Hourly incremental sync + pre-dunning run + nightly sweep (incl. deletion detection)
  • Voided-after-sync cancellation handling
  • Synthetic payments for marked-as-paid invoices
  • Dry-run mode + per-run quality reporting + alerting with PS visibility
  • Hosting, monitoring and operation on Reviaflow EU infrastructure
  • Runbook + architecture documentation, handover-ready codebase

OUT OF SCOPE — v1

  • Real-time webhook layer (endpoint reserved at infra level; available as a later evolution)
  • Refunds flow (zero real cases — runtime guard only, § 9)
  • Anything related to the Salesforce connection: its matching, dedup, contact enrichment, or fixes to Kolsquare's SF→Hyperline feed (§ 13)
  • Dunning plans, reminder policies, recipient policy — Upflow onboarding configuration
  • Hyperline-side configuration (native reminders toggle, reconciliation cadence) — merchant-side
  • Draft invoices (never synced)
  • Historical settled invoices older than ~1 year (unless chained to an open invoice)
  • Kolsquare data cleanup (duplicate SF IDs, missing emails) — reported, not fixed at source
  • Additional merchants — separate onboarding, quoted per merchant

12. Open items

Non-blocking for the build; each lands before its build phase:

  • OPEN uncollectible transitions post-sync (1 today): WRITTEN_OFF not API-writable → flagged in the quality report for manual write-off in the Upflow UI (Upflow/merchant action).
  • OPEN external payment-method semantics (483 transactions) → instrument mapping, awaiting Kolsquare.
  • OPEN Final list of optional custom fields (service period, public URL, PO/reference) — definitions provisioned ×3 orgs.
  • OPEN isMain vs manual curation in Upflow — build detail.
  • OPEN Credit on an already-settled invoice: allocate vs unapplied credit — build detail.
  • OPEN Dunning recipient policy (all vs main) — Upflow/Kolsquare onboarding decision (data in § 5).

13. Decision record

Salesforce is out of connector scope (settled 17 Jul, confirmed in writing). Upflow's guidance: Hyperline is the source of truth for customer creation; the SFDC connection is secondary, optional enrichment ("I wouldn't worry about SFDC here"). Decisions built on that guidance:

  • Customers are keyed on the Hyperline id (externalId = cus_…): 100% coverage, unique, immutable. The Salesforce Account ID is carried as custom field salesforce_account_id where present.
  • The connector takes no responsibility for the future SFDC connection's matching or dedup behaviour. If that connection, once plugged, fails to match existing customers or creates duplicates, resolution belongs to that project (Upflow onboarding + Kolsquare), not to this connector.
  • What the connector still provides for that future wiring: salesforce_account_id on every linked customer + an informational SF-link coverage report at every run.

Sign-off trail: ownership, org topology, voided handling, import scope — Sarah-Nicole in writing, 17 Jul 2026 · customer key framing — explicit confirmation ask, confirmed same day.