Lydira API
TR

Import guides

Opening balances

Open invoices and supplier bills brought over from your previous system.

Open invoices and supplier bills carried over from your previous system on cut-over day. An amount already paid comes in as a brought-forward receipt.

On this page

A key with one of these scopes reaches it:importimport_issue

Invoices (receivables)operator_invoices

POST/api/v1/imports/operator_invoices

Upsert: re-sending the same external_id updates the existing row.

Endpoints

  • validatePOST /api/v1/imports/operator_invoices/validate
  • importPOST /api/v1/imports/operator_invoices
  • feedGET /api/v1/imports/operator_invoices/records
  • read_backGET /api/v1/imports/operator_invoices/records/{external_id}

A new row must carry

legacy_numberissued_ontotal_amountone of customer_external_id | bill_to_name

Fields(11)
  • external_idstring
  • legacy_numberstringrequired
  • issued_ondaterequired
  • due_ondate
  • total_amountmoneyrequired
  • amount_paidmoney

    already collected before cutover; imported as a brought-forward receipt

  • paid_ondate

    when amount_paid was collected; defaults to the invoice date

  • currencycurrency
  • bill_to_namestring
  • customer_external_idreference
  • notesstring

References

  • customer_external_id → customers · matched by external_id, email · when missing error

Reading it back

Once the agency works the record (confirms it, numbers the tickets, invoices it) this is what GET /api/v1/imports/{entity}/records/{external_id} answers, and what every webhook delivers. detail carries what only the agency can add after your push.

GET /api/v1/imports/operator_invoices/records/OPERATOR-INVOICE-1001
200
{
  "entity": "operator_invoices",
  "external_id": "OPERATOR-INVOICE-1001",
  "source_system": "crm",
  "type": "OperatorInvoice",
  "id": "9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18",
  "created_at": "2026-03-14T09:30:00Z",
  "updated_at": "2026-03-15T11:05:00Z",
  "status": "issued",
  "currency": "EUR",
  "totals": {
    "total": "1250.0",
    "paid": "0.0",
    "balance": "1250.0"
  }
}

Request · dry run, every field

curl -X POST 'https://YOUR-CELL.lydira.com/api/v1/imports/operator_invoices/validate' \
  -H 'Authorization: Bearer sek_YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: 8f14e45f-ea2c-4f33-9a3b-6d0c1b7e5a90' \
  -d '{
  "source_system": "crm",
  "rows": [
    {
      "external_id": "OPERATOR-INVOICE-1001",
      "legacy_number": "2025-000431",
      "issued_on": "2026-03-14",
      "due_on": "2026-03-18",
      "total_amount": "1250.00",
      "amount_paid": "1250.00",
      "paid_on": "2026-03-14",
      "currency": "EUR",
      "bill_to_name": "Lovelace Seyahat A.Ş.",
      "customer_external_id": "CUSTOMER-1001",
      "notes": "Imported from the source system."
    }
  ]
}'
Response
200
{
  "import": {
    "id": "9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18",
    "entity": "operator_invoices",
    "source_system": "crm",
    "status": "ready",
    "company_id": "9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18",
    "stats": {
      "total": 1,
      "will_create": 1,
      "will_update": 0,
      "created": 0,
      "updated": 0,
      "skipped": 0,
      "invalid": 0,
      "failed": 0,
      "not_selected": 0
    },
    "error": null,
    "created_at": "2026-03-14T09:30:00Z",
    "links": {
      "self": "/api/v1/imports/9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18",
      "rows": "/api/v1/imports/9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18/rows"
    },
    "mode": "validate",
    "async": false,
    "on_conflict": "skip",
    "pricing": "apply_rules"
  },
  "ignored_fields": [],
  "results": [
    {
      "row": 1,
      "external_id": "OPERATOR-INVOICE-1001",
      "status": "will_create"
    }
  ]
}

Supplier bills (payables)supplier_bills

POST/api/v1/imports/supplier_bills

Upsert: re-sending the same external_id updates the existing row.

Endpoints

  • validatePOST /api/v1/imports/supplier_bills/validate
  • importPOST /api/v1/imports/supplier_bills
  • feedGET /api/v1/imports/supplier_bills/records
  • read_backGET /api/v1/imports/supplier_bills/records/{external_id}

A new row must carry

numberreceived_attotal_amountsupplier_external_id

Fields(10)
  • external_idstring
  • numberstringrequired
  • received_atdaterequired
  • due_ondate
  • total_amountmoneyrequired
  • amount_paidmoney

    already paid before cutover; imported as a brought-forward payment

  • paid_ondate

    when amount_paid was paid; defaults to the bill date

  • currencycurrency
  • supplier_external_idreferencerequired
  • notesstring

References

  • supplier_external_id → suppliers · matched by external_id, code · when missing error

Reading it back

Once the agency works the record (confirms it, numbers the tickets, invoices it) this is what GET /api/v1/imports/{entity}/records/{external_id} answers, and what every webhook delivers. detail carries what only the agency can add after your push.

GET /api/v1/imports/supplier_bills/records/SUPPLIER-BILL-1001
200
{
  "entity": "supplier_bills",
  "external_id": "SUPPLIER-BILL-1001",
  "source_system": "crm",
  "type": "SupplierBill",
  "id": "9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18",
  "created_at": "2026-03-14T09:30:00Z",
  "updated_at": "2026-03-15T11:05:00Z",
  "status": "open",
  "currency": "EUR",
  "totals": {
    "total": "1250.0",
    "paid": "0.0",
    "balance": "1250.0"
  }
}

Request · dry run, every field

curl -X POST 'https://YOUR-CELL.lydira.com/api/v1/imports/supplier_bills/validate' \
  -H 'Authorization: Bearer sek_YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: 8f14e45f-ea2c-4f33-9a3b-6d0c1b7e5a90' \
  -d '{
  "source_system": "crm",
  "rows": [
    {
      "external_id": "SUPPLIER-BILL-1001",
      "number": "TR-2025-000431",
      "received_at": "2026-03-14",
      "due_on": "2026-03-18",
      "total_amount": "1250.00",
      "amount_paid": "1250.00",
      "paid_on": "2026-03-14",
      "currency": "EUR",
      "supplier_external_id": "SUPPLIER-1001",
      "notes": "Imported from the source system."
    }
  ]
}'
Response
200
{
  "import": {
    "id": "9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18",
    "entity": "supplier_bills",
    "source_system": "crm",
    "status": "ready",
    "company_id": "9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18",
    "stats": {
      "total": 1,
      "will_create": 1,
      "will_update": 0,
      "created": 0,
      "updated": 0,
      "skipped": 0,
      "invalid": 0,
      "failed": 0,
      "not_selected": 0
    },
    "error": null,
    "created_at": "2026-03-14T09:30:00Z",
    "links": {
      "self": "/api/v1/imports/9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18",
      "rows": "/api/v1/imports/9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18/rows"
    },
    "mode": "validate",
    "async": false,
    "on_conflict": "skip",
    "pricing": "apply_rules"
  },
  "ignored_fields": [],
  "results": [
    {
      "row": 1,
      "external_id": "SUPPLIER-BILL-1001",
      "status": "will_create"
    }
  ]
}

The flow

  1. Dry-run. POST …/validate runs the same path and writes nothing.
  2. Send. The same body without /validate. A bad row fails alone and names its field.
  3. Read back. GET /api/v1/imports/{entity}/records/{external_id} answers with your own key.
  4. Listen. Webhooks tell you when the agency changes the record.

Conventions →Webhooks →