Lineo Finance — Broker Integration API (1.1.0)

Download OpenAPI specification:

Lineo Finance Engineering: engineering@lineo.finance

API for broker partners to integrate with the Lineo Finance onboarding and data-sharing platform.

The integration covers two independent concerns:

  • Lead onboarding — register a new prospective customer who is not yet on Lineo.
  • Connection establishment — link an existing Lineo customer to the broker partner for ongoing data sharing.

Lead onboarding — POST /v1/broker/leads

A single endpoint supports two sub-flows, determined by the has_existing_tax_advisor Boolean field.

Flow A — Customer without existing tax advisor (has_existing_tax_advisor false or omitted)

  1. Register a leadPOST /v1/broker/leads submits customer data. Lineo internally matches a tax advisory partner, generates the service contract PDF, initiates Yousign electronic signing and returns status: "contract_sent" with a signature_link for iFrame embedding.
  2. Customer signs — The customer reviews and signs the contract inside the iFrame. Status transitions to contract_signed.
  3. Partner countersigns — The matched tax advisor countersigns. Status transitions to active. Lineo then creates the customer account and sends the activation email with a password-set link. No further API calls are required from the broker.

Flow B — Customer with existing tax advisor (has_existing_tax_advisor true)

  1. Register a leadPOST /v1/broker/leads submits customer data + tax_advisor_contact and returns status: "awaiting_third_party". No signature link is returned.
  2. Advisor claims the lead — Lineo contacts the tax advisor via email. Once the advisor accepts, the contract is generated with that advisor as partner; status transitions to contract_sent (signature link becomes available).
  3. Customer signs → partner countersigns → active — same as Flow A from this point on.

Auto-provisioned data-sharing connection

If external_customer_reference is supplied at lead registration, Lineo will, upon transition to active, automatically materialise a data-sharing connection for the resulting customer. No separate POST /v1/broker/connections call is required for the lead-flow case. The connection.activated webhook is emitted alongside lead.status.active.

Connection establishment for existing customers — POST /v1/broker/connections

For customers who are already Lineo customers (registered manually, via another broker partner, or via a previous lead) and now want to connect their broker account for data sharing, the broker calls POST /v1/broker/connections with the customer's Handelsregister identifier (hrb_court + hrb_number) plus the broker-side customer reference. Consent for data sharing is governed by the partnership contract — the broker is responsible for capturing and retaining customer consent on their side.

On success the connection is created in active state and the broker receives the Lineo company_id plus connection_id. On HRB lookup miss the broker receives 404.

Connections can be queried (GET) and revoked (DELETE) symmetrically.

Status tracking (both surfaces)

The broker can poll GET /v1/broker/leads/{leadId}/status and GET /v1/broker/connections/{connectionId} or receive real-time webhook notifications on state changes.

Authentication

All endpoints require an X-Api-Key header. API keys are provisioned by Lineo during partner onboarding.

Webhook Notifications

If a webhook URL is configured for your broker account, Lineo will POST a signed JSON payload to that URL on every lead status transition and connection lifecycle event. See the Webhooks section below for the payload schema and verification instructions.

Leads

Lead registration and onboarding lifecycle for new prospective customers

Register a lead and initiate onboarding

Submits customer data and initiates the appropriate onboarding flow based on the has_existing_tax_advisor field:

  • false (default): Generates a service contract PDF, initiates Yousign electronic signing, and returns a signature_link for iFrame embedding.
  • true: Requires tax_advisor_contact. Lineo contacts the tax advisor asynchronously. Returns status: "awaiting_third_party" with no signature link.

Idempotency: Leads are unique per broker by (hrb_court, hrb_number). If an active lead with the same HRB already exists for your broker, the existing lead data is returned with is_existing: true and HTTP 200 OK regardless of whether other fields (email, representative name, external_customer_reference) match. To override fields on an existing active lead, contact Lineo support.

Conflict (409): Two distinct conflict conditions, checked in order:

  1. HRB already known to Lineo. The supplied HRB belongs either to an existing Lineo customer (regardless of how that customer entered the system — converted from a previous lead, registered manually, or linked via another broker) or to an active lead with a different broker. In both cases the lead cannot be created. If the company is an active customer, use POST /v1/broker/connections instead.
  2. Representative email already a Lineo user. Only checked if the HRB is unknown. The supplied representative email is already bound to an existing Lineo ApplicationUser. Lead conversion would fail downstream because user emails are unique. Contact Lineo support to link the new company to the existing user account.
Authorizations:
ApiKey
Request Body schema: application/json
required
external_customer_reference
string <= 100 characters

Optional broker-side identifier for this customer. If provided, Lineo persists it on the lead and, on transition to active, automatically creates a data-sharing connection so no separate POST /v1/broker/connections call is needed for lead-flow customers. The value is opaque to Lineo — round-tripped in RegisterLeadResponse, LeadStatusResponse, all webhook payloads, and used to identify the customer when Lineo pulls data from the broker's API. Brokers whose data-export API requires a per-customer reference (for example Vivid's referral_code) should always supply this field. Brokers without such a requirement may omit it.

company_name
required
string <= 200 characters

Registered company name.

hrb_court
required
string (XJustizGerichtsId)
Enum: "B1204" "B1601" "B2609" "B2805" "D2102" "D2201" "D2304" "D2404" "D2505" "D2601" "D2803" "D2910" "D3101" "D3201" "D3304" "D3310" "D3410" "D3413" "D3508" "D4102" "D4201" "D4301" "D4401" "D4501" "D4608" "D4708" "D5701" "F1103" "G1103" "G1207" "G1309" "G1312" "H1101" "K1101" "M1103" "M1114" "M1201" "M1202" "M1203" "M1301" "M1305" "M1405" "M1406" "M1502" "M1602" "M1603" "M1607" "M1608" "M1706" "M1710" "M1809" "M1906" "N1105" "N1206" "N1209" "N1308" "P1103" "P2106" "P2204" "P2305" "P2408" "P2507" "P2613" "P2716" "P3101" "P3210" "P3313" "R1101" "R1102" "R1105" "R1202" "R1304" "R1402" "R1504" "R1608" "R1901" "R2101" "R2103" "R2108" "R2201" "R2204" "R2307" "R2402" "R2404" "R2503" "R2507" "R2602" "R2604" "R2706" "R2707" "R2713" "R2809" "R2909" "R3101" "R3103" "R3201" "R3208" "R3306" "T2101" "T2210" "T2214" "T2304" "T2408" "T3104" "T3201" "T3304" "T3403" "U1104" "U1206" "U1308" "V1102" "V1103" "V1104" "V1105" "V1107" "V1109" "V1110" "V1111" "V1112" "V1115" "W1215" "X1112" "X1321" "X1517" "X1721" "Y1101" "Y1102" "Y1105" "Y1106" "Y1108" "Y1109" "Y1110" "Y1111" "Y1112" "Y1113" "Y1114" "Y1201" "Y1203" "Y1205" "Y1206" "Y1208" "Y1209" "Y1210" "Y1214" "Y1301" "Y1302" "Y1303" "Y1304" "Y1307" "Y1308"

German court identifier as an XJustiz GDS.Gerichte code (the official XÖV codelist). Example: D2601 = Amtsgericht München.

hrb_number
required
string <= 50 characters

Handelsregister number.

street
required
string <= 200 characters

Street and house number of the registered office.

postal_code
required
string <= 10 characters ^\d{5}$

German postal code (PLZ).

city
required
string <= 100 characters

City of the registered office. Also used as the signing-place city on the contract.

first_name
required
string <= 100 characters

Representative's first name.

last_name
required
string <= 100 characters

Representative's last name.

email
required
string <email> <= 254 characters

Representative's email address. For customers without an existing tax advisor, Yousign will send an OTP to this email during contract signing.

phone
string <= 16 characters

Representative's phone number (optional) in E.164 format: '+' followed by 1-15 digits, first digit non-zero.

has_existing_tax_advisor
boolean
Default: false

Set to true if the customer already has a tax advisor they want to continue working with. When true, tax_advisor_contact is required.

object (TaxAdvisorContact)

Contact information for the customer's existing tax advisor. Required when has_existing_tax_advisor is true.

Responses

Request samples

Content type
application/json
Example
{
  • "external_customer_reference": "vivid-2026-01-abc123",
  • "company_name": "Muster GmbH",
  • "hrb_court": "D2601",
  • "hrb_number": "HRB 123456",
  • "street": "Teststraße 1",
  • "postal_code": "10115",
  • "city": "Berlin",
  • "first_name": "Max",
  • "last_name": "Mustermann",
  • "email": "max.mustermann@example.de",
  • "phone": "+491701234567"
}

Response samples

Content type
application/json
Example
{}

Query lead status

Returns the current status and key timestamps for a lead owned by the authenticated broker.

Authorizations:
ApiKey
path Parameters
leadId
required
string <uuid>

The lead identifier returned by the registration endpoint.

Responses

Response samples

Content type
application/json
{
  • "lead_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  • "external_customer_reference": "vivid-2026-01-abc123",
  • "status": "contract_signed",
  • "assigned_partner_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  • "partner_name": "Steuerberatung Schmidt",
  • "created_at": "2026-04-13T10:00:00Z",
  • "contract_signed_at": "2026-04-13T10:15:00Z",
  • "activated_at": null,
  • "connection_id": null
}

Connections

Data-sharing connection establishment for existing Lineo customers

Establish a data-sharing connection with an existing Lineo customer

Creates a data-sharing link between the calling broker and an existing Lineo customer identified by Handelsregister (HRB).

Use this endpoint when the customer is already a Lineo customer (registered manually, via another broker partner, or via a previous lead that has reached active state) and now wants to add this broker as a data source.

For new customers that are not yet on Lineo, use POST /v1/broker/leads instead. If external_customer_reference was supplied at lead registration, the connection is created automatically when the lead reaches active — no separate call needed.

Idempotency. A connection is uniquely identified by (broker_partner, external_customer_reference). Re-posting with the same external_customer_reference for the same broker returns 200 OK with is_existing: true (the existing connection is returned). Re-posting with a different external_customer_reference for an HRB that is already connected to this broker returns 409 Conflict.

HRB lookup. If no Lineo company matches the supplied hrb_court + hrb_number, the response is 404. The broker may then either (a) start the lead-onboarding flow via POST /v1/broker/leads, or (b) inform the customer that no matching Lineo customer was found.

Authorizations:
ApiKey
Request Body schema: application/json
required
external_customer_reference
required
string <= 100 characters

Broker-side identifier for this customer grant. Lineo persists it on the connection and uses it to identify the customer when pulling data from the broker's API. Must be unique per broker.

hrb_court
required
string (XJustizGerichtsId)
Enum: "B1204" "B1601" "B2609" "B2805" "D2102" "D2201" "D2304" "D2404" "D2505" "D2601" "D2803" "D2910" "D3101" "D3201" "D3304" "D3310" "D3410" "D3413" "D3508" "D4102" "D4201" "D4301" "D4401" "D4501" "D4608" "D4708" "D5701" "F1103" "G1103" "G1207" "G1309" "G1312" "H1101" "K1101" "M1103" "M1114" "M1201" "M1202" "M1203" "M1301" "M1305" "M1405" "M1406" "M1502" "M1602" "M1603" "M1607" "M1608" "M1706" "M1710" "M1809" "M1906" "N1105" "N1206" "N1209" "N1308" "P1103" "P2106" "P2204" "P2305" "P2408" "P2507" "P2613" "P2716" "P3101" "P3210" "P3313" "R1101" "R1102" "R1105" "R1202" "R1304" "R1402" "R1504" "R1608" "R1901" "R2101" "R2103" "R2108" "R2201" "R2204" "R2307" "R2402" "R2404" "R2503" "R2507" "R2602" "R2604" "R2706" "R2707" "R2713" "R2809" "R2909" "R3101" "R3103" "R3201" "R3208" "R3306" "T2101" "T2210" "T2214" "T2304" "T2408" "T3104" "T3201" "T3304" "T3403" "U1104" "U1206" "U1308" "V1102" "V1103" "V1104" "V1105" "V1107" "V1109" "V1110" "V1111" "V1112" "V1115" "W1215" "X1112" "X1321" "X1517" "X1721" "Y1101" "Y1102" "Y1105" "Y1106" "Y1108" "Y1109" "Y1110" "Y1111" "Y1112" "Y1113" "Y1114" "Y1201" "Y1203" "Y1205" "Y1206" "Y1208" "Y1209" "Y1210" "Y1214" "Y1301" "Y1302" "Y1303" "Y1304" "Y1307" "Y1308"

German court identifier as an XJustiz GDS.Gerichte code (the official XÖV codelist). Example: D2601 = Amtsgericht München.

hrb_number
required
string <= 50 characters

Handelsregister number.

Responses

Request samples

Content type
application/json
{
  • "external_customer_reference": "vivid-2026-01-abc123",
  • "hrb_court": "D2601",
  • "hrb_number": "HRB 123456"
}

Response samples

Content type
application/json
{
  • "connection_id": "5f9b1e1f-2c08-4f8e-9b3b-1c5e6d7a9b10",
  • "lineo_company_id": "7c8f70f7-1234-5678-9abc-def012345678",
  • "external_customer_reference": "vivid-2026-01-abc123",
  • "status": "active",
  • "created_at": "2026-04-15T09:30:12Z",
  • "is_existing": true
}

Get connection status

Returns the current state of a connection owned by the authenticated broker.

Authorizations:
ApiKey
path Parameters
connectionId
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "connection_id": "5f9b1e1f-2c08-4f8e-9b3b-1c5e6d7a9b10",
  • "lineo_company_id": "7c8f70f7-1234-5678-9abc-def012345678",
  • "external_customer_reference": "vivid-2026-01-abc123",
  • "status": "active",
  • "created_at": "2026-04-15T09:30:12Z",
  • "revoked_at": null,
  • "revocation_reason": null,
  • "is_existing": true
}

Revoke a data-sharing connection

Marks the connection as revoked and stops all subsequent data pulls. Idempotent: revoking an already-revoked connection returns 200 OK with the existing revocation timestamp.

Use this when the customer revoked sharing on the broker's side, or when the broker administratively wants to terminate the link. Customer-initiated revocations from the Lineo side will produce a connection.revoked webhook instead.

Authorizations:
ApiKey
path Parameters
connectionId
required
string <uuid>
query Parameters
reason
string
Default: "customer_request"
Enum: "customer_request" "broker_admin" "contract_terminated" "other"

Why the connection is being revoked. Stored in the audit log.

Responses

Response samples

Content type
application/json
{
  • "connection_id": "5f9b1e1f-2c08-4f8e-9b3b-1c5e6d7a9b10",
  • "lineo_company_id": "7c8f70f7-1234-5678-9abc-def012345678",
  • "external_customer_reference": "vivid-2026-01-abc123",
  • "status": "revoked",
  • "created_at": "2026-04-15T09:30:12Z",
  • "revoked_at": "2026-08-01T14:22:00Z",
  • "revocation_reason": "customer_request",
  • "is_existing": false
}

Webhooks

Outbound webhook payload schemas (for reference — not callable endpoints)