Skip to content

Catalog import formats

This is the specification for the files the catalog importer reads. For the workflow that consumes them — where the importer lives, choosing add-versus-stage, and resolving records afterward — see Catalog import.

Five file types, up to 50 MB per upload:

ExtensionFormat
.mrcMARC 21 binary
.marcMARC 21 binary, same format, other extension
.csvOne of the three templates below
.xlsxOne of the three templates below, as an Excel worksheet
.xlsThe same, in the older Excel format Destiny still writes

One import carries any number of files, in either format, in any combination: MARC files (.mrc, .marc) and spreadsheets (.xlsx, .xls, .csv), up to 50 MB each. Several files of one template is a normal case — a shelf list report split across four workbooks is one import. A workbook with a sheet per item type counts as several files: each sheet is read on its own. Lyra tells the two Excel formats apart from the file itself, so a report saved straight out of your old system works without a conversion step.

Each import is scoped to a single library. Holdings fields carry no library code; copies for multiple libraries require a separate import per library.

A spreadsheet import comes in three templates rather than one catch-all format. All three are independently optional, and one upload can carry any combination of them, including several files of the same template.

TemplateFor
Non-book itemsGlobes, microscopes, kits, equipment — no ISBN
Books by ISBNBooks, identified by ISBN
Books by titleBooks with no ISBN, identified by title and author

Each sheet holds its header row and nothing else. Fill in the ones you need and leave the rest alone — a sheet with nothing under its header row is ignored, so an unused tab costs nothing and the whole book goes up as one file. Working in a workbook also sidesteps the two ways an Excel-exported CSV gets mangled: there is no encoding to guess at, and a long ISBN stays the digits it shows rather than turning into scientific notation.

You do not pick the template — Lyra reads it off the file. Drop your files in and each one’s column headings — each sheet’s, in a workbook — decide which template it is: an isbn column means Books by ISBN, an author column with no ISBN means Books by title, and anything else means Non-book items. The dialog names what it decided on each file’s row, with a control to correct it before anything is imported. That last case is the only ambiguous one — a file carrying a title and no author and no ISBN is equally an equipment list and a book list, and Non-book items is the guess because that is exactly what that template looks like filled in sparsely.

Before a template can be read off a file at all, the file has to carry the column that template keys its rows by.

TemplateNeeds
Non-book itemsA title column
Books by ISBNAn isbn column
Books by titleA title column

Every template can be picked for any file. A file that lacks the template’s column, or whose headings aren’t all Lyra’s own, goes through the column mapping step before it imports, and that step won’t let the import go ahead until one of the file’s columns is mapped to the template’s column. It says what’s missing, for example message: Books by ISBN needs an ISBN column..

Your headings do not have to match the template’s spelling. Case, punctuation and underscores are ignored (Call Number, call_number and CALL NUMBER are one column), and each of the three column tables below carries a Recognized headings column listing the other labels read as that Lyra column.

A file whose headings are all Lyra’s own column names imports as it is. Any other heading, recognized here or not, sends the file through the column mapping step, where you confirm what each column holds. The recognized headings are where Lyra’s suggestions start; after them it guesses from the words a heading shares with a Lyra column’s name, and leaves anything else for you. A heading that isn’t listed here can still be mapped by hand.

Those labels are the ones Follett Destiny, Alexandria, Atriuum, Koha and Sirsi put on the same handful of concepts. Unlike the roster importer’s, they mean the same thing on all three templates, so a heading reads the same way whichever template a file turns out to be.

Line Number, Copy Status and Circulations are recognized and ignored — an ordinal or a circulation statistic is not an error in the file, and neither is imported. In the mapping step they, and any column Lyra can’t place, start as setting: Don't import. Each Lyra column goes to one of your columns; in a file that skips the mapping step because it uses Lyra’s own names, a column name that appears twice is read from the leftmost.

Each row is one copy, not one item. Rows describing the same thing collapse into a single item with several copies — see Grouping rows into items and copies.

ColumnRecognized headingsAccepted valuesNotes
title
Required
—Any stringBlank surfaces the row as a missing-title exception.
description
Optional
—Any stringBlank leaves it empty.
image_url
Optional
—An http/https URLInvalid or non-HTTP values are ignored. Non-book items get no automatic cover.
target_audience
Optional
—One of the audience valuesUnrecognized or blank becomes UNKNOWN.
acquisition_date
Optional
Date Added, Date AcquiredA date (see value formats)Blank or unparseable leaves it empty.
barcode
Optional
Holdings Barcode, Copy BarcodeAny stringPer-copy. Blank surfaces the row as a missing-barcode exception.
call_number
Optional
Call NumberAny stringPer-copy shelf location.
location
Optional
Sublocation, Sublocation(s)A location namePer-copy. New locations are created automatically in Metadata.
purchase_price
Optional
Price, Purchase PriceA number, e.g. 39.99Per-copy. Invalid values are ignored.
circulates
Optional
—true / yes or false / no (case-insensitive)false makes the copy reference only. Blank or unrecognized defaults to true.

You provide the ISBN plus the few fields that can’t be looked up; the importer fills the rest from Lyra’s book-data provider.

ColumnRecognized headingsAccepted valuesNotes
isbn
Required
—One ISBN-10 or ISBN-13 (hyphens optional)The lookup key. ISBN-10s are converted to ISBN-13 automatically. One ISBN per row: a cell holding several, as a Destiny export writes them, is rejected. A blank cell surfaces the row as a missing-title exception; a cell that can’t be read surfaces it as an unreadable-ISBN one.
target_audience
Optional
—One of the audience valuesBlank becomes UNKNOWN.
series_name
Optional
—Any stringBlank leaves it empty.
lexile_score
Optional
—An integer multiple of 5, e.g. 650Invalid values are ignored.
reading_grade
Optional
—A number from 0 to 12 (tenths allowed), e.g. 3.5Invalid values are ignored.
acquisition_date
Optional
Date Added, Date AcquiredA date (see value formats)Per-copy. Blank or unparseable leaves it empty.
barcode
Optional
Holdings Barcode, Copy BarcodeAny stringPer-copy. Blank surfaces the row as a missing-barcode exception.
call_number
Optional
Call NumberAny stringPer-copy shelf location.
location
Optional
Sublocation, Sublocation(s)A location namePer-copy. New locations are created automatically.
purchase_price
Optional
Price, Purchase PriceA numberPer-copy. Invalid values are ignored.
circulates
Optional
—true / yes or false / no (case-insensitive)Blank or unrecognized defaults to true.

The lookup fills in title, authors, description, cover image, topics, page count, paperback, and copyright year — but only where your file left them blank. The four item-level fields you can set (target_audience, series_name, lexile_score, reading_grade) are never looked up at all.

A column your file does carry always wins. The blank template above leaves out the eight looked-up columns because a librarian filling one in by hand should not have to supply what the ISBN already answers. A file that does supply them — a Lyra export, or a report from your old system — is read as written, so a title you corrected in Lyra comes back as the title you corrected rather than as whatever the ISBN currently resolves to. The extra columns are title, authors, description, image_url, topics, page_count, published_year and paperback, and multi-value fields are semicolon-joined. They answer to recognized headings too: Author or Author's Name for authors, Publication Year or Pub Year for published_year.

For books your old system exported without an ISBN. Nothing is looked up — the item is exactly what the row says it is. The blank template has no cover, description or subject columns, because a shelf list has none of them; a file that carries description, image_url or topics anyway is read, which is what lets a Lyra export of ISBN-less books come back whole.

ColumnRecognized headingsAccepted valuesNotes
title
Required
—Any stringBlank surfaces the row as a missing-title exception.
authors
Optional
Author, Author's NameOne or more names, semicolon-separatedWritten as your file has them, Last, First and all. A contribution goes in parentheses: Pilkey, Dav;Beard, George (Illustrator).
target_audience
Optional
—One of the audience valuesBlank becomes UNKNOWN.
series_name
Optional
—Any stringBlank leaves it empty.
lexile_score
Optional
—An integer multiple of 5, e.g. 650Invalid values are ignored.
reading_grade
Optional
—A number from 0 to 12 (tenths allowed), e.g. 3.5Invalid values are ignored.
acquisition_date
Optional
Date Added, Date AcquiredA date (see value formats)Per-copy. Blank or unparseable leaves it empty.
barcode
Optional
Holdings Barcode, Copy BarcodeAny stringPer-copy. Blank surfaces the row as a missing-barcode exception.
call_number
Optional
Call NumberAny stringPer-copy shelf location.
location
Optional
Sublocation, Sublocation(s)A location namePer-copy. New locations are created automatically.
purchase_price
Optional
Price, Purchase PriceA numberPer-copy. Invalid values are ignored.
circulates
Optional
—true / yes or false / no (case-insensitive)Blank or unrecognized defaults to true.

There is no isbn column: a file with one is read as Books by ISBN instead, which is the better import where you have the ISBNs.

  • Headers. A header row is expected, and it is the first row of the file or sheet. Columns may be in any order, header names are matched by the rules above or by the mapping you confirmed, columns mapped to setting: Don't import are ignored, and any omitted column is treated as blank. Whitespace around every value is trimmed.
  • Unreadable rows. A row with the wrong number of fields is skipped and listed under tab: Skipped with the reason and its row number; the rest of the file still imports. Rows are never shifted to fit, so a title with an unescaped comma is reported rather than silently importing into the wrong columns. Many exporters end every file with a blank or whitespace-only line, and that line is skipped this way.
  • Nothing usable. A Books by ISBN file where not one row holds a readable ISBN, or a Non-book items file where not one row holds a title, is refused rather than imported as empty records. The reason is on the import’s tab: Skipped tab.
  • Dates. acquisition_date accepts ISO dates (2024-09-01) and common natural-language forms (Sept 1, 2024). Anything unparseable is left empty rather than failing the row.
  • Booleans. circulates accepts true/yes and false/no, case-insensitively. Blank or unrecognized defaults to true.
  • Encoding. Detected from the file: UTF-8, UTF-16, or Windows-1252 — the last being what Follett Destiny and Excel on Windows write — so accented titles and authors survive whichever your old system produced. A byte-order mark is removed. Text that was already mangled before you exported it is imported as written rather than guessed at. A spreadsheet has no encoding to detect: .xlsx stores its text one way, so accents come across whatever wrote the file.
  • Spreadsheets. .xlsx and .xls are read the same way. Every sheet in a workbook is read, each on its own: its first row is its header, matched by the same rules as a CSV’s, and the template is worked out from that sheet’s own columns — so one book holding a sheet of books and a sheet of equipment imports both. A sheet with nothing below its header row is ignored. In the import dialog each sheet gets its own row under the file, labelled with the tab’s own name; the import’s page lists the workbook once, as the single file you uploaded, and a skipped row names where it came from as report.xlsx · Equipment. Cells keep the type Excel gave them: a date cell imports as the day it shows rather than as a serial number, a price or a barcode stored as a number comes across as written, and TRUE/FALSE read as booleans do. A row with nothing in any cell is ignored, so the blank rows at the end of a report cost nothing; a row with values in columns the header row never named is skipped and listed under tab: Skipped, the same as a CSV row with the wrong number of fields.
  • Refused files. A file is refused before the import runs, on the row it sits on in the dialog, when it is larger than 50 MB (message: This file is too large.), empty (message: There is nothing in it.), has no readable header row (message: There is no header row.), is a workbook whose every sheet has column names and nothing below them, such as an unfilled template (message: There are no records in it.), will not open as the kind of file its extension claims (message: This file could not be read., or message: This is not a MARC 21 file. for a .mrc that does not start with a MARC record leader). A file whose columns don’t match a template isn’t refused: it goes to the column mapping step instead. Refusing one file or one sheet doesn’t cost you the rest of the upload.

Bad values in individual fields never fail or flag a record. An unparseable date, price, Lexile, ATOS level, or image URL is left empty so the rest of the record still imports.

Both templates share one audience vocabulary: the MARC 21 Target Audience Term List, the code carried in the MARC 008 control field at position 22, which Lyra also reads directly from MARC records. Each value maps to an age range shown throughout the staff app and OPAC.

ValueMARC codeShown asAge range
PRESCHOOLaPreschoolages 0–5
PRIMARYbPrimaryages 6–8
PREADOLESCENTcPreadolescentages 9–13
ADOLESCENTdAdolescentages 14–17
ADULTeAdultages 18+
JUVENILEjJuvenilegeneral non-adult, no specific age
GENERALgGeneralno specific age
SPECIALIZEDfSpecializedno specific age
UNKNOWN#Unknownno specific age

Values are matched case-insensitively. Anything else, including blank, becomes UNKNOWN.

The age range is also what the OPAC’s reading-level bands fall back on when a title has no ATOS level and no Lexile measure. JUVENILE carries an explicit search span of grades K–8 despite having no MARC age; GENERAL, SPECIALIZED, UNKNOWN, and ADULT carry no band signal, so a title relying on one of those matches no band. See Search & holds.

non-book-items.csv:

title,description,image_url,target_audience,acquisition_date,barcode,call_number,location,purchase_price,circulates
Globe of the World,A 12-inch physical and political globe.,,UNKNOWN,2024-09-01,NB-0001,912 GLO,Reference,39.99,false
Microscope Kit,Student microscope with prepared slides.,,UNKNOWN,2024-09-01,NB-0002,502 MIC,STEM cart,89.00,true

books.csv:

isbn,target_audience,series_name,lexile_score,reading_grade,acquisition_date,barcode,call_number,location,purchase_price,circulates
9781536208429,UNKNOWN,,,,2024-09-01,BK-0001,E LAW,Picture books,16.99,true
9781536222715,UNKNOWN,Jasmine Green Rescues,,,2024-09-01,BK-0002,FIC PET,Fiction,7.99,true

On import this creates two non-book items (a reference-only globe and a microscope kit that circulates), each with one copy; and looks up both ISBNs to create two books with full bibliographic data, one copy each, keeping the series_name provided for the second.

When Lyra reads a MARC record, it pulls these fields into the item record. Fields not listed are ignored.

MARC fieldWhat it becomes in Lyra
008 (target audience)Target audience — the age band shown throughout Lyra. Read from control-field position 22. When that position is blank, Juvenile (j) or General (g), a sharper note decides instead: the Accelerated Reader interest level in 526 $b (LG → Primary, MG → Preadolescent, MG+ and UG → Adolescent), then an interest grade level in 521 (first indicator 2, such as Grades 1-3), then an interest age level in 521 (first indicator 1, such as Ages 9-12).
020 (ISBN)Item ISBN. Used for edition grouping.
082 $a $b (Dewey number)Copy call number, but only as a fallback for a record that carries no holdings field.
100 / 700 (personal name authors)Item authors. Each name becomes a record in Metadata. Corporate (110/710) and meeting (111/711) names are not read.
245 (title)The item’s single title — subtitle ($b), part ($p), and number ($n) fold in as Title: Subtitle.
260 / 264 $c (publication year)Four-digit publication year. Place and publisher subfields are not read.
300 (description)Page count and a paperback hint.
490 $a / 830 $a (series)Series name. Resolved to a series record in Metadata.
520 (summary)Item description.
521 / 526 (reading level)Lexile measure and Accelerated Reader fields.
6XX (subjects)Item topics. Flattened to uncontrolled book topics in Lyra. See Metadata.
852 / 876 / 952 (holdings)Copy records — one copy per holdings field. See below.
856 $u (electronic location)Cover image, when $u links to an image file (.jpg, .png, .webp) and the field is marked as one: a second indicator of 2, or a $3 of Image, which is how OverDrive labels its covers.

Copies come from a record’s holdings fields. Lyra recognizes three holdings conventions and reads whichever one a record uses, checking in this order and stopping at the first it finds:

  1. 952 — Lyra- and Koha-style holdings. This is the convention Lyra itself writes on export (see Catalog export), so a MARC file exported from one Lyra library re-imports through this path.
  2. 876 + 852 — the MARC 21 Holdings format, where each 876 (item) is paired with its parent 852 (holding).
  3. 852 — plain 852 holdings, the Follett/Destiny style.

Each holdings field becomes one copy, with subfields mapped to copy attributes:

Copy attribute952876 + 852852
Call number$o852 $k + $h + $i$k + $h + $i
Barcode$p876 $p$p
Location$c852 $b + $c$b + $c

Where two or more subfields feed one attribute, they’re joined into a single value. Acquisition date and purchase price come across too when the record carries them. New locations are created automatically in Metadata.

With 952 holdings, a copy marked withdrawn ($0) is skipped, and one marked not for loan ($7) imports as reference only.

A record with no holdings fields at all still imports as one copy — call number taken from the 082 Dewey number if present, and no barcode. Because it has no barcode, the import holds it in tab: Issues.

A MARC record from OverDrive, such as its free MARC Express records, becomes a digital item rather than an item with copies. Lyra recognizes one by any of:

  • an 037 whose $b names OverDrive, which carries the item’s Reserve ID in $a
  • an 001 control number of the form ODN0000573705
  • an 856 link to link.overdrive.com

The OverDrive title ID comes from the 001, or from the titleID in the 856 link when the 001 is someone else’s. It is what an import matches on, so importing an item again updates it instead of adding it twice. A record that looks like OverDrive’s but has no title ID is read as an online record from another provider (see below).

What Lyra readsFrom
Digital magazineLeader position 07 is s (a serial).
AudiobookLeader position 06 is i, or a 336 $b of spw, or a 337 $a of audio.
EbookAny other OverDrive record.
NarratorA 700 name that a 511 note introduces as Narrator:.

A digital item never gets copies. Holdings fields (852, 876, 952) on an OverDrive record are ignored, including the barcodes OverDrive can add for schools. The 655 genre terms Electronic books and Electronic journals are left out of topics, because they say how the title is delivered rather than what it is about.

A record that describes an online resource in at least two ways — an 007 starting cr, a 006 or leader position 06 of m, online resource in its 300 or 338, or [electronic resource] in its 245 $h — but isn’t OverDrive’s is flagged status: Online resource, whether or not it carries barcodes. button: Mark as physical clears the flag, and the record then needs what any physical record needs, such as a title and barcodes. Ignoring it is the other way out.

Each spreadsheet row, and each MARC holdings field, is one copy. Before creating anything, the importer groups records that describe the same item so they land as one item with several copies rather than several near-duplicate items. What counts as “the same item” depends on the type.

Grouped by ISBN, then by title and author.

isbn is the primary join key: records sharing an ISBN become one item (one edition) with multiple copies. When an ISBN is missing or doesn’t match, Lyra falls back to title and author — records for the same work (matching title and the same set of author names, compared case-, accent-, punctuation-, and order-insensitively) join the same item.

Per-item fields (title, authors, topics, and so on) should be identical across grouped rows: the importer keeps one item’s worth of them and appends the copy-level fields (barcode, call_number, location, acquisition_date, purchase_price, circulates) from every row.

  • Duplicate MARC records collapse. Three records for the same book with the same ISBN become one item with three copies. The same holds within one spreadsheet and across the files in one upload.
  • Different editions of one work join one item. A paperback and a hardback of the same title and author import as a single item with two editions — one copy each — because the differing ISBN becomes a new edition of the matched work rather than a whole new item. A book with no ISBN still lands on its work.
  • Title-and-author matching needs a named author. A book with no listed author falls back to the non-book rules below, so it won’t merge on title alone.
  • Matching extends to the existing catalog. Both the ISBN join and the title-and-author join attach to an item already in the library, not only to other records in the same import.

Grouped by matching item-level details. Non-book items carry no ISBN, so the importer joins on the item fields themselves: title, description, image_url, and target_audience. Rows whose four fields all match, after trimming and normalization, collapse into one item — one copy per row, with the copy-level fields varying.

  • To load several copies of one non-book item, repeat the same title, description, image_url, and target_audience on each row and vary only the copy columns.
  • Any difference in those four fields makes a separate item — a typo in the description or a different audience is enough.
  • Matching extends to the existing catalog. Re-importing a non-book already held adds a copy to the existing item rather than creating a duplicate. Where the catalog already holds two items with the same four fields, the row joins the first.

Every parsed record lands in exactly one bucket. The catalog importer has no per-field error codes; a record is flagged for one or more of the reasons below, or not at all. A digital item has no copies, so it never lands in tab: Added copies; the import counts it under message: Digital items.

BucketMeaning
tab: Added copiesParsed cleanly and is in the catalog.
tab: Ready to addClean, with no remaining issues, waiting to be committed.
tab: IssuesCouldn’t be added automatically. Flagged for one or more of the reasons below.
tab: IgnoredSet aside by hand.
tab: SkippedCouldn’t be read at all.
tab: Digital itemsDigital items the file added, or updated because they were already in the catalog. Only shown for a file that carried digital items.
tab: Not in this fileNot a bucket for this file’s records: the digital items already in the catalog that the file left out. Only shown for a file that carried digital items.
Issue flagCause
status: Missing titleAn empty title in a non-book file, a missing 245 in MARC, or a book row whose ISBN was blank or found no ISBNdb record — and that matched nothing in the catalog.
status: Unreadable ISBNA book row whose isbn cell held something Lyra can’t read as an ISBN.
status: Missing barcodesA copy with no barcode: a blank barcode cell, an 852 with no $p, or the placeholder copy on a MARC record with no holdings field.
status: Duplicate barcodesA barcode colliding with a copy already in the library, or with another row in the same import.
status: Online resourceA MARC record for an online resource from a provider other than OverDrive, with or without barcodes. See Online records from other providers.

A titleless row whose ISBN does match an edition already held is not flagged: it needs no title of its own, and its copies join the existing item.

The tab: Skipped tab covers invalid MARC structure, wrong encoding, and empty records; for a spreadsheet or CSV it covers a row whose fields don’t line up with the header row — too few or too many in a .csv, a value past the last named column in a sheet — and a whole file that was refused. Everything the importer could read still lands in the buckets above, so one bad row never costs you the file.