Lydira API
TR

Import guides

Customers, suppliers and leads

The people and companies your bookings point at. Import them first.

Customers, suppliers and leads are what your bookings point at, so they go in first. Re-sending one updates it rather than duplicating it.

On this page

A key with one of these scopes reaches it:importimport_issue

Customerscustomers

POST/api/v1/imports/customers

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

Endpoints

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

A new row must carry

name

Fields(16)
  • external_idstring

    source primary key → ExternalReference

  • namestringrequiredPII
  • customer_typeenum

    One of:individualcorporate

  • emailemailPII
  • phonephonePII
  • legal_namestring
  • tax_numbertax_number
  • tax_officestring
  • address_linestringPII
  • address_districtstringPII
  • address_citystringPII
  • address_statestringPII
  • address_zipstringPII
  • preferred_currencycurrency
  • codestring
  • notesstringPII

    free text; imported as a customer note

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/customers/records/CUSTOMER-1001
200
{
  "entity": "customers",
  "external_id": "CUSTOMER-1001",
  "source_system": "crm",
  "type": "Customer",
  "id": "9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18",
  "created_at": "2026-03-14T09:30:00Z",
  "updated_at": "2026-03-15T11:05:00Z",
  "invoices": [
    {
      "id": "4b8e1f60-7c2d-4e9a-b3f5-0a6d2c9e8b71",
      "number": "LYD2026000000117",
      "status": "issued",
      "currency": "EUR",
      "total": "1250.0",
      "balance": "1250.0"
    }
  ]
}

Request · dry run, every field

curl -X POST 'https://YOUR-CELL.lydira.com/api/v1/imports/customers/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": "CUSTOMER-1001",
      "name": "Ada Lovelace",
      "customer_type": "individual",
      "email": "ada@example.com",
      "phone": "+905551112233",
      "legal_name": "Lovelace Seyahat A.Ş.",
      "tax_number": "1234567890",
      "tax_office": "Beşiktaş",
      "address_line": "Nispetiye Cad. No:12",
      "address_district": "Beşiktaş",
      "address_city": "İstanbul",
      "address_state": "",
      "address_zip": "34340",
      "preferred_currency": "EUR",
      "code": "AC-1001",
      "notes": "Imported from the source system."
    }
  ]
}'
Response
200
{
  "import": {
    "id": "9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18",
    "entity": "customers",
    "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": "CUSTOMER-1001",
      "status": "will_create"
    }
  ]
}

Supplierssuppliers

POST/api/v1/imports/suppliers

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

Endpoints

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

A new row must carry

name

Fields(16)
  • external_idstring
  • namestringrequired
  • supplier_typeenum

    integer-backed enum — resolved against TravelSupplier.supplier_types

    One of:otherairlinehoteldmccruisetour_operatorinsuranceactivitytransferrailcar_rentalconsolidatorgdsvisacharteragencycateringtechnicalproductiondecorationvenuephoto_videoentertainmentsecuritystaffingbus

  • codestring
  • iata_codestring
  • emailemail
  • phonephone
  • country_codestring
  • tax_numbertax_number
  • tax_officestring
  • address_linestringPII
  • address_districtstringPII
  • address_citystringPII
  • address_statestringPII
  • address_zipstringPII
  • websitestring

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/suppliers/records/SUPPLIER-1001
200
{
  "entity": "suppliers",
  "external_id": "SUPPLIER-1001",
  "source_system": "crm",
  "type": "TravelSupplier",
  "id": "9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18",
  "created_at": "2026-03-14T09:30:00Z",
  "updated_at": "2026-03-15T11:05:00Z"
}

Request · dry run, every field

curl -X POST 'https://YOUR-CELL.lydira.com/api/v1/imports/suppliers/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-1001",
      "name": "Ada Lovelace",
      "supplier_type": "hotel",
      "code": "AC-1001",
      "iata_code": "TK",
      "email": "ada@example.com",
      "phone": "+905551112233",
      "country_code": "TR",
      "tax_number": "1234567890",
      "tax_office": "Beşiktaş",
      "address_line": "Nispetiye Cad. No:12",
      "address_district": "Beşiktaş",
      "address_city": "İstanbul",
      "address_state": "",
      "address_zip": "34340",
      "website": "https://example.com"
    }
  ]
}'
Response
200
{
  "import": {
    "id": "9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18",
    "entity": "suppliers",
    "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-1001",
      "status": "will_create"
    }
  ]
}

Leadsleads

POST/api/v1/imports/leads

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

Endpoints

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

A new row must carry

name

Fields(12)
  • external_idstring
  • namestringrequiredPII
  • emailemailPII
  • phonephonePII
  • stageenum

    One of:inboxqualifiednurturingproposalwonlost

  • sourcetaxonomy

    Your account's lead_source list; it starts with:website_formreferralwalk_ininbound_emailphonesocial_mediapartnervoice_capturebusiness_cardother

  • estimated_valuemoney
  • currencycurrency
  • party_sizeinteger
  • destinationsstring
  • customer_external_idreference

    links to an imported customer

  • notesstringPII

References

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

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/leads/records/LEAD-1001
200
{
  "entity": "leads",
  "external_id": "LEAD-1001",
  "source_system": "crm",
  "type": "Lead",
  "id": "9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18",
  "created_at": "2026-03-14T09:30:00Z",
  "updated_at": "2026-03-15T11:05:00Z",
  "currency": "EUR"
}

Request · dry run, every field

curl -X POST 'https://YOUR-CELL.lydira.com/api/v1/imports/leads/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": "LEAD-1001",
      "name": "Ada Lovelace",
      "email": "ada@example.com",
      "phone": "+905551112233",
      "stage": "inbox",
      "source": "website_form",
      "estimated_value": "1250.00",
      "currency": "EUR",
      "party_size": 2,
      "destinations": "Roma, Floransa",
      "customer_external_id": "CUSTOMER-1001",
      "notes": "Imported from the source system."
    }
  ]
}'
Response
200
{
  "import": {
    "id": "9d2f7c3a-1b4e-4a7d-8e51-2c0f6b9a4d18",
    "entity": "leads",
    "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": "LEAD-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 →