Showing Posts From

Batch

Canva Bulk Create: The Limits, and What to Do When You Hit Them

Canva Bulk Create: The Limits, and What to Do When You Hit Them

We make a tool that competes with part of what Canva does, so weigh this accordingly. It's also true that most people reading this should probably stay where they are, and this post says where that line is. Canva's Bulk Create is a good feature. You build a design, connect a spreadsheet, map columns to text and image placeholders, and get a personalized copy per row. For name badges, social variants and simple certificates, it is often the fastest path from data to output, and if it's working for you there's no reason to change anything. But there's a specific set of walls people hit, and hitting one tends to send you searching. Here's what they are. Wall 1: rows per batch Bulk Create caps how many rows you can process in one go. Canva's help center documents the current figure, which has been in the low hundreds, and the cap applies per batch, so a larger dataset means splitting the file and repeating the process. The documented cap is usually not the real limit anyway. Each row becomes a page in a single Canva document, so a few hundred rows produces a few hundred pages in one file, and the editor gets progressively heavier to work with. In practice most people find their comfortable batch size well below the technical maximum. Not because it stops working, but because reviewing and exporting a 300-page document is its own chore. If you're generating a few hundred items a few times a year, splitting the file is genuinely fine. If it's a recurring weekly job, the splitting is the problem. Wall 2: it's a human-in-the-editor flow This is the bigger one, and it's structural rather than a number you can raise. Bulk Create is something a person does: open the design, connect the data, map the fields, generate, review, export. There is no version of it that fires when a form is submitted, when an order completes, or when a row lands in a database. Someone has to be at the keyboard. That's fine for campaign work. You sit down, you make the batch, you're done. It doesn't work at all for anything continuous. If your certificates should be issued the moment a learner finishes a course, or the voucher should be in the welcome email that goes out ninety seconds after signup, no amount of batch processing gets you there. You need something a server can call. Wall 3: programmatic access is gated high Canva does have a developer platform. The Connect APIs include autofill endpoints that populate a brand template from data programmatically, which is exactly the capability the previous section is asking for. The catch is the plan requirement. Per Canva's own documentation, using the Autofill APIs in production requires the integration to act on behalf of a user in a Canva Enterprise organization; users on other paid plans get limited access while an integration is under development. If you're a solo operator or a small team on Pro or Teams, that path isn't open to you at the price you're currently paying. So the honest summary is that automated generation exists in the Canva ecosystem, and it's priced for organizations rather than for the person with a spreadsheet and a deadline. Wall 4: the details that surface at scale Smaller than the first three, but they're what people actually complain about once volume goes up. No per-field validation before generating. Bulk Create maps whatever is in the cell. If row 88 has a malformed date or a code in the wrong format, you find out by looking at page 88. At twenty rows you'd notice. At three hundred you won't, and the error reaches whoever receives it. Unique codes per row need care. A single QR code on a design is easy. A different QR code per row, one encoding each recipient's own redemption or verification URL, is a different requirement, and it's worth testing on three rows before you commit a whole campaign to it. Print output. Canva exports print-quality PDFs, but if your requirement is a specific DPI, exact physical dimensions, and predictable behaviour when a print shop opens the file, this is worth verifying carefully rather than assuming. Long values break layouts. A name twice as long as your test data will overflow or wrap unless the text element is set up to handle it. This bites everyone, in every tool, and it's the single most common cause of a batch that has to be regenerated. Option A: stay, and split Worth saying plainly: if you generate a few hundred items a handful of times a year, splitting the spreadsheet costs you fifteen minutes per campaign. That is cheaper than migrating, cheaper than learning a new tool, and cheaper than adding a subscription. Canva's design capabilities and asset library are genuinely excellent, and none of the walls above are about design quality. Split by something meaningful, like cohort or date or region, rather than by arbitrary row ranges, and the resulting files stay organized on their own. Option B: write a script If you're comfortable with code, generating personalized images from a CSV is a solid afternoon of Python or Node. You get complete control and no subscription. You also get to own it. Font rendering, the PDF library's quirks, and the layout code all become yours to maintain, and the person who needs the design changed next quarter has to ask you rather than doing it themselves. That trade is worth it for some teams and clearly not for others. Option C: a tool built for the batch case The third option is a design editor whose batch and API paths aren't an afterthought. This is what we built Zandovi to be, and here's the concrete comparison rather than a pitch. Batch from a spreadsheet. Design once, download a CSV whose headers already match your template's variable names, fill it, upload it. Rows are validated against the template's rules before anything renders, so mismatched columns, missing required values, values outside a variable's allowed list and QR data that won't encode all get caught up front — along with an advisory flag on any column whose values run far longer than the design allows for. You fix them in the sheet and re-upload. Then you get a ZIP with one file per row, rather than a many-page document to export. Row caps per job are 25 on the free plan, 100 on Personal, 200 on Studio, 300 on Team and 400 on Business. So this is not an unlimited-rows story either, and large datasets still get split. What changes is the validation and the output shape. The same design, callable. The template you built for the batch flow is also an API endpoint: POST the variable values, get PNG, JPEG, WebP or PDF bytes back. Every paid plan includes full API access, with no enterprise tier standing between you and automating it. That's the wall-2 and wall-3 answer in one. Unique codes per row are the normal case. QR and barcode elements bind to variables like any text field, so each row can carry its own redemption link or verification URL without a workaround. Print output is explicit. DPI is a setting (96, 150 or 300), PDF costs the same as a PNG with no format multiplier, and the canvas can be set up in millimetres or inches from the start.Where Canva is still the better answer Being fair about this matters more than winning the comparison. Design breadth is the obvious one. The stock library, the font selection, the sheer number of starting points: that's Canva's moat, and it's a real one. So is familiarity. If four people need to edit the design and all four already use Canva, that's worth more than any feature comparison. Occasional, low-volume batches don't justify adding a tool either. A few hundred items twice a year is not a problem worth solving with a second subscription. And if you're already on Teams or Enterprise, the API question is settled and brand controls come with it. The case for moving is narrower than a vendor blog usually admits: you're generating regularly, the volume makes the manual flow tedious, you need validation or unique codes per row, or you need a server to trigger it and don't have Enterprise. Moving one design, if you do Don't migrate everything. Pick the single design causing the most repetitive work and rebuild just that one:Rebuild the layout on a canvas of the same dimensions. An hour, usually less. Mark the changing elements as variables, setting which are required and which have a fixed list of allowed values. This is the step with no Canva equivalent, and it's what stops bad rows from becoming bad output. Download the generated CSV template and paste your existing data under the headers. Run a batch of five rows first. Check the longest name, the shortest name, and anything with an accent or a non-Latin character. Then run the real batch.The free plan includes 100 renders a month with no card, which is enough to rebuild one design and test it properly before deciding anything.References: Canva Bulk Create help, Canva Connect Autofill API docs. Both were checked in July 2026. Canva's limits and plan requirements change, so confirm the current figures on their pages before making a decision.

How to Generate Certificates From a Spreadsheet (CSV to ZIP, No Mail Merge)

How to Generate Certificates From a Spreadsheet (CSV to ZIP, No Mail Merge)

The course finished on Friday. Two hundred and thirty people attended. Each of them needs a certificate with their own name spelled correctly, the course title, the completion date, and something that makes it look like it came from an organization rather than from a word processor at 11pm. You have all of that in a spreadsheet already. The gap is turning 230 rows into 230 files. Why the usual routes hurt Mail merge. Word and Google Docs will merge names into a document, and for plain text on white paper that's fine. Certificates aren't plain text. They're a layout, with a border, a logo, a signature block, and typography that has to sit exactly where you put it. Merging into a designed document tends to nudge things by a few pixels per record, and you find out at print time. Duplicating slides. The 230-slides-in-a-deck approach. It works, and it costs an entire afternoon, and any change to the design means doing it again. Design-tool bulk features. Better, and genuinely the right tool for some jobs. The limits show up as row caps, no automation hook, and export formats that aren't print-ready. A script. If you're comfortable with code, generating certificates from a CSV in Python is a solid afternoon's work. Then you own the layout code, the font loading, and the PDF generation forever. What follows is the fourth route: design the certificate once in an editor, mark the parts that change, upload the spreadsheet, download a ZIP. Step 1: design the certificate Start from a certificate template or a blank canvas. If these will be printed, set the canvas up for print from the start: pick an A-series or US Letter preset in landscape, and set the export DPI to 300. Doing this first matters. A canvas sized for the screen and scaled up afterwards is how you end up with a soft logo on a printed certificate.Lay out the fixed parts: border, organization logo, the words "Certificate of Completion", the signature line. These never change, so they're just design. Step 2: mark what changes as variables This is the step that turns a design into a generator. Select each element that differs per person, mark it as a variable, and give it a name:Variable Element Notesrecipient_name text Set auto-fit so "Bartholomew Featherstonehaugh" and "Li Wei" both look intentional.course_title text Usually identical across the batch. Give it a default value and you can leave the column out.completion_date text Dates travel through as text, so format them in the spreadsheet exactly as they should print.certificate_id text Mark it required so a blank cell is caught rather than rendering an empty line.verify_qr QR code Encodes a verification URL. See below.Give every variable a description too. It shows up as guidance later, and if someone else ever fills the spreadsheet, that one sentence prevents most of the back-and-forth. Where a column should only ever hold a handful of known values, set its Allowed values list. Type in the real values and anything else in that column is rejected before rendering, which is the cheapest way to stop a typo becoming 230 wrong certificates. A note on the QR code. Binding a QR element to a variable lets each certificate carry its own verification link, https://yoursite.com/verify/{certificate_id}, which is how you make a certificate checkable rather than merely decorative. Keep the QR element at least 100×100 px and use the Print Safe button to get the quiet zone right; QR codes printed too small or too close to a border are the number one reason scans fail on paper.Step 3: get the CSV with the right headers Click Generate, then the Batch tab, then Download CSV Template. This gives you a CSV whose header row already matches your variable names exactly. Use it. The most common failure in bulk generation is a column called Name when the template expects recipient_name, and starting from the generated file removes that entire category of problem. Open it in Excel, Google Sheets or Numbers, and paste your data underneath. One row per certificate: recipient_name,course_title,completion_date,certificate_id,verify_qr Ana Silva,Advanced Data Modelling,12 Sep 2026,CERT-2026-0001,https://example.com/verify/CERT-2026-0001 Marek Nowak,Advanced Data Modelling,12 Sep 2026,CERT-2026-0002,https://example.com/verify/CERT-2026-0002 Yuki Tanaka,Advanced Data Modelling,12 Sep 2026,CERT-2026-0003,https://example.com/verify/CERT-2026-0003If you're building the ID and verification URL from a spreadsheet formula, double-check the first and last rows after filling down. Off-by-one errors in a fill-down are invisible until someone scans a code and lands on the wrong person's record. Step 4: upload and let validation do its job Drag the completed CSV into the upload area. Three things happen before anything renders. Your column headers are matched against the variable names, so a missing required column is flagged immediately and any column the template doesn't recognise is called out as ignored. Then every row is checked: a missing required value, a value outside a variable's allowed list, or QR data too long to encode all get reported with the row and column named. Finally, any column whose values run much longer than the default you designed around is flagged as a fit risk, so you find out that one name is three times the length of the rest before it shrinks to unreadable. You get a summary like "3 errors in 230 rows" with a table naming each one. Fix them in the spreadsheet, re-upload, re-validate. This step is the whole reason to prefer a validated batch over a script you wrote on Thursday. Catching three bad rows before rendering costs you two minutes. Catching them after you've printed and mailed 230 certificates costs considerably more.Step 5: choose your output, then submit Pick the format and resolution. Use PDF at 300 DPI for anything going to a printer or a print shop, and PNG at 2× scale for anything going into an email or a download link. Then Submit Batch. The job appears in the list below with a status of PENDING, PROCESSING, COMPLETED or FAILED, along with the row count and how long ago you submitted it. When it's done, Download Results gives you a ZIP with one file per row. If a job comes back FAILED, expanding it in the list tells you which rows failed and why. Renders that fail are refunded to your quota, and a batch rejected at validation is never charged at all, so a failed job doesn't cost you anything except the time to fix and resubmit. The row limits, stated plainly Batch jobs have a per-job row cap that depends on your plan:Plan Rows per jobFree 25Personal 100Studio 200Team 300Business 400So a 230-person course is one job on Team, two on Studio, three on Personal. The practical workaround for a larger cohort is to split the spreadsheet by cohort, session or date, which is usually how you want the files organized anyway. Sort the sheet first, then split; that way each ZIP maps to something meaningful rather than to an arbitrary row range. Every rendered row counts as one render against your monthly pool, the same as an API call. 230 certificates is 230 renders. On the $29 Personal plan that's 5,000 renders a month, so the certificates for a busy training calendar fit comfortably; on the free plan's 100 renders, a single mid-sized cohort will use most of it. There's also a maximum output resolution that varies by plan. The free plan tops out around A5 at 300 DPI, paid plans go to A4/US Letter and above. If you're producing large-format certificates, check that before designing the canvas rather than after. Making the files easy to hand out Two things worth deciding before you generate rather than after. The first is file naming. Files in the ZIP are named from your data, so having a certificate_id column pays for itself here. A ZIP of CERT-2026-0001.pdf files is trivially matchable against your attendee list. A ZIP of certificate-1.pdf files is not. The second is delivery. If you're emailing these individually, keep the same CSV as the source of truth: it already has the name, the ID, and, if you add a column, the email address. The ZIP and the sheet then line up row for row, and whatever you use to send the mail can join them without a manual matching step. When to move from the spreadsheet to the API The batch flow is a browser workflow: a person uploads a file and downloads a ZIP. That's the right shape when certificates are an event. A cohort finishes, you generate a set. It's the wrong shape when certificates are a continuous stream. If your platform issues one the moment a learner finishes a course, at unpredictable times, you want the same template called from your backend instead: one POST per completion, PDF bytes back, attached to an email or stored against the learner record. Same template, same variables, no spreadsheet. Most teams end up using both. The API covers the automated path, and the batch tab covers the "we ran a workshop and need 40 certificates by Thursday" path that never quite fits the automated one.The batch generation guide covers the dialog in detail, and the free plan gives you 100 renders a month so you can try a real cohort without a card.

Designing Gift Cards People Actually Redeem

Designing Gift Cards People Actually Redeem

A gift card is an unusual product. Someone pays you today for something you owe later, to a person who didn't choose it. Every card that gets forgotten in a drawer looks like free revenue on this month's numbers and is really a promise sitting on your books, plus a customer who never came in. Breakage rates get quoted anywhere from a few percent to well into double digits, and the honest answer is that it depends entirely on the business. What isn't in doubt is the direction: the easier a card is to understand and use, the more of them come back through the door. A lot of that is design. So this covers what makes a card get redeemed, and then the mechanical part most guides skip: producing a whole set of denominations and codes without laying out each one by hand. Make the value unmissable The amount is the most important element on the card, and it should look like it. Give it more size and weight than anything else, including your logo. The failure mode is a card designed to be tasteful, where the value ends up as small grey text in a corner. Someone pulls it out of an envelope, can't immediately see what it's worth, and puts it back. Hold the design at arm's length. If the number isn't the first thing you read, the hierarchy is wrong. Contrast matters as much as size. A pale gold $50 on a cream background photographs beautifully and is genuinely hard to read in a dim restaurant. Make the redemption path obvious Every question a recipient has to ask costs you redemptions. The card needs to answer four things without anyone thinking about it: what it's worth, where it can be used, how to use it, and whether it expires. That last one deserves care. Gift card expiry is regulated in many places, with minimum validity periods and rules about fees, and the rules differ by country and by state. Check what applies to you rather than copying what another card does. If there's no expiry, saying so plainly is a feature worth printing. Keep the how-to-use line short and specific. "Present this card in store or enter the code at checkout" beats a paragraph of terms. If you need terms, put them on the back in small type where they belong. Design the set, not the card Here's where most gift card projects go wrong. You design a beautiful $25 card, then you need $50, $100 and $250. Then December arrives and you need a festive version of all four. Then a corporate client wants fifty with their logo on them. Designing each one separately means every future change is four to sixteen edits, and they drift apart. One gets the new logo, another keeps the old typography, and after a year your cards don't look like a family. The fix is one master template where the parts that change are variables:Variable Element Notesamount text Format it in the sheet exactly as it should print: $50, not 50.card_code text Mark it required, so a blank cell is caught rather than printing a codeless card.expires_at text Dates print exactly as written, so settle the format in the spreadsheet.occasion text Set its Allowed values to the occasions you actually produce.redeem_qr QR code Encodes the redemption URL for that specific card.Now a new denomination is a row in a spreadsheet, and a rebrand is one edit to one template.Codes that survive being typed by a human If your cards carry a code, someone will read it off a physical card and type it into a phone. Design for that. Drop ambiguous characters from your alphabet. 0 and O, 1 and I and l, 5 and S, 8 and B all cause support tickets, and you lose nothing by excluding them. Group the code so the eye can track it: H4T9-QK2M-7RVX is meaningfully easier to transcribe than H4T9QK2M7RVX. Set the code in a monospace font. Proportional fonts make similar characters harder to distinguish at a glance, and monospace signals "this is a code you type" without a label saying so. Then mark card_code required, so a batch with a blank code fails at upload rather than at the print shop. Generate the codes in the spreadsheet and check the first and last rows after filling down — an off-by-one there is invisible until someone tries to redeem. The QR code beside it does the same job with less friction. Bind a QR element to a variable and each card carries its own redemption link, so a phone can skip the typing entirely. Keep it at least 100×100 px and use the Print Safe button to get the quiet zone right, because a QR crowded against a card edge is a QR that doesn't scan. Match the occasion without forking the design A birthday card and a corporate thank-you shouldn't feel the same, but they should feel like they came from the same business. Handle this with the occasion variable and a swappable image element rather than separate templates. The layout, typography and logo placement stay fixed. The photograph and one or two colours change. Stock imagery is searchable inside the editor across Unsplash, Pexels and Pixabay, so sourcing a seasonal image doesn't mean leaving the app. The discipline is keeping the structure identical across occasions. That's what makes a set of cards read as a range rather than as four unrelated designs. Produce the whole set at once With the template built, the set is a spreadsheet. Download the CSV template from the Batch tab so the headers already match your variable names: amount,card_code,expires_at,occasion,redeem_qr $25,H4T9-QK2M-7RVX,31 Dec 2027,Birthday,https://example.com/gc/H4T9QK2M7RVX $50,P7WD-3NXA-K9TF,31 Dec 2027,Birthday,https://example.com/gc/P7WD3NXAK9TF $100,R2MK-8VQH-XD4N,31 Dec 2027,Thank You,https://example.com/gc/R2MK8VQHXD4NUpload it and every row is validated before anything renders. A missing card code, an occasion outside the allowed values you set on that variable, a column whose name doesn't match the template: all flagged with the row named, so you fix the sheet rather than the output. Then submit and download a ZIP with one file per row. Row caps per job are 25 on Free, 100 on Personal, 200 on Studio, 300 on Team and 400 on Business, so a run of 500 corporate cards gets split across a few jobs. Split them by denomination or by client and each ZIP is something you can hand over as it is.Print and digital are different exports For physical cards, export PDF at 300 DPI. Set the canvas up in millimetres or inches from the start rather than converting later, and pick the DPI before you design, since the options are fixed at 96, 150 and 300. There's no bleed or crop-mark support, so if your design runs colour to the edge, ask your printer what bleed they need and add it by oversizing the canvas yourself, keeping the trim area clear of anything important. Worth knowing before you send the file rather than after. For emailed cards, PNG at 2× scale is the right output. Same template, different export, so the digital and physical versions can't drift apart. What this doesn't do Zandovi generates the card. It doesn't track balances, mark a code as spent, or tell you whether card H4T9-QK2M-7RVX has already been used. That lives in your POS or your ecommerce platform, and it's the part that turns a printed code into a working gift card. Worth being clear about, because a beautifully produced set of cards with no system behind the codes is a set of cards anyone can spend twice. When the spreadsheet stops fitting Batch generation suits how most businesses actually buy gift cards: a run before the holidays, a corporate order, a restock. It stops fitting when cards are sold online and expected instantly. If someone buys a digital gift card at 11pm and wants it in their inbox, you want the same template called from your backend: one POST carrying that card's amount and code, PNG or PDF bytes back, attached to the delivery email. Same template, same variables, nobody at a keyboard. What this costs A run of 100 cards is 100 renders. The free plan's 100 renders a month covers a first batch or a proper test. Personal at $29/month for 5,000 renders covers a seasonal programme comfortably, and manual exports from the editor don't count against it on any paid plan.There are eleven gift card templates in the gallery to start from, and the batch generation guide walks through the upload and validation step by step.

How to Number Event Tickets (And Why the Number Isn't Enough)

How to Number Event Tickets (And Why the Number Isn't Enough)

Two hundred tickets for a fundraiser. You design one, it looks good, and then you hit the part nobody writes about: making all two hundred different from each other. The naive version is a sequential number in the corner. That's worth doing, but be clear about what it buys you. A printed number stops you double-selling seat 47 and gives you something to write on a refund note. It does not stop anyone photographing a ticket and showing the photo at the door, because the number on the photo is just as valid as the number on the paper. So this covers both halves: producing the run with real per-ticket data, and making the ticket checkable rather than merely numbered. What a ticket has to do Three jobs, and they pull in different directions. It has to look like your event, which is a design problem. It has to be readable in about two seconds by someone standing in a doorway in bad light, which is a typography problem. And each one has to be distinguishable from every other one, which is a data problem. Most ticket tutorials only solve the first. The door test is the one people underestimate. Whoever is checking tickets is looking for the date, the tier, and whether it's real. Put those three where the eye lands first and let the artwork be artwork. A beautiful ticket that makes someone squint at 7pm is a worse ticket. Start from a template if one fits You don't have to design from nothing. There are 13 ticket designs in the template gallery, covering concerts, festivals, theatre, raffles, parking, sports, conferences and a few others. Open the gallery, choose the Tickets tab, and open whichever sits closest to your event. You can change every colour, font and element afterwards, so pick on layout rather than on palette. Be clear about what that actually saves you. A template gives you the composition and the artwork, which is the slow part. It does not arrive pre-wired with variables, and it's built on a 1200×600 px canvas rather than a physical paper size. So everything below still applies: you set the units and DPI yourself, and you mark your own variables in Step 2. What you skip is the blank page and the hour of nudging things into alignment. Step 1: set the canvas up for print before you design Open the New Canvas dialog and pick from the Tickets preset category, or set your own dimensions. If you're sizing manually, switch the units from pixels to millimetres or inches first. Designing in physical units and letting the app compute the pixels is much less error-prone than picking a pixel size and hoping it lands on a sane paper size. Set the export DPI to 300 now rather than later. The DPI options are fixed at 96, 150 and 300, so this isn't a free-form field you can fine-tune afterwards, and a canvas laid out for screen then pushed to print is how you get a soft logo on 200 pieces of card.One thing to know up front: there's no bleed or crop-mark support. If your design runs colour to the edge and you're using a commercial printer, ask them what bleed they want, then add it yourself by making the canvas that much larger and keeping the trim area clear of anything important. For home printing on perforated stock this doesn't come up. Step 2: decide what changes per ticket Everything that differs between ticket 1 and ticket 200 becomes a variable. Select the element, mark it as a variable, then give it a name:Variable Element Notesticket_number text Pad to a fixed width in the sheet so leading zeros survive. 0047 sorts and reads better than 47.tier text Set its Allowed values to your real tiers, so a typo in the sheet is caught before printing.holder_name text Only if tickets are named. Turn on auto-fit so long names don't overflow.seat text Optional, with the same allowed-values trick as tier if seats come from a fixed set.verify_qr QR code The half that actually matters. See below.Add a description to each one. If someone else fills the spreadsheet later, that single sentence prevents most of the questions. The fixed parts, meaning the event name, date, venue and artwork, stay as ordinary design. They're the same on every ticket, so they never touch your data. Step 3: build the numbers in your spreadsheet Here's the honest bit: there is no auto-increment feature. Zandovi doesn't generate a sequence for you. The numbers come from the CSV you upload, which means your spreadsheet is what produces them. That's less of a limitation than it sounds, because a spreadsheet is genuinely good at this and it leaves the sequence under your control. Download the CSV template from the Batch tab so your headers already match the variable names, then fill down: ticket_number,tier,seat,verify_qr 0001,General,A1,https://example.com/t/0001-8F3K 0002,General,A2,https://example.com/t/0002-QW7P 0003,VIP,B1,https://example.com/t/0003-M2XRTwo habits worth adopting. Pad the numbers to a fixed width (0001, not 1) so they sort correctly and look deliberate. And don't make the verification URL guessable: append a short random suffix to the sequential part, as above. A purely sequential URL means anyone holding ticket 0003 can guess 0004 through 0200. When you're done filling down, check the first and last rows. Off-by-one errors in a fill-down are invisible until someone at the door scans a code that belongs to a different person. Step 4: the QR code is the part that does the work Bind a QR element to the verify_qr variable and every ticket carries its own link. This is the difference between a ticket that looks unique and one that is unique, because the code encodes something your system can check when it's scanned. Three constraints matter once it's on paper. The QR element has a 75×75 px minimum, and 100×100 is the sensible floor, because smaller codes fail to scan at exactly the moment you can't afford it. Use the Print Safe button to get the quiet zone right, since the four-module margin around the code is what lets a scanner find it at all. And test the real printed output before committing to the run: print one, then scan it with the oldest phone you can find, in bad light. If your door hardware is a laser scanner rather than a phone, use a barcode element instead. CODE128 handles alphanumeric ticket IDs, with EAN13, UPC, CODE39 and ITF14 also available. Barcodes have their own minimums of 100 px wide and 40 px tall. One caveat worth stating plainly: generating the code is not the same as validating it. Zandovi produces a ticket carrying a unique URL. Whether that URL has already been used at the door is a question for whatever sits behind it, whether that's your event platform, a spreadsheet someone ticks off, or a small app you write. If nothing checks the code, the QR is decoration. Step 5: let validation catch the bad rows Upload the CSV in the Batch tab. Before anything renders, your headers are matched against the variable names and every row is checked against the template's rules. Missing required values get flagged, as does a tier outside your allowed values, or QR data too long to encode. This step matters more for tickets than for almost anything else, because the failure is expensive and late. A bad row in a set of certificates costs you a reprint. A bad row in a set of tickets costs you an argument at the door with someone holding a ticket that doesn't scan.Fix the flagged rows in the sheet, re-upload, re-validate, then submit. Step 6: generate and print Choose PDF at 300 DPI for anything going to a printer. The job appears in the list with a status of PENDING, PROCESSING, COMPLETED or FAILED, and when it's done, Download Results gives you a ZIP with one file per row. Row caps per job depend on your plan: 25 on Free, 100 on Personal, 200 on Studio, 300 on Team, 400 on Business. So a 200-ticket run is one job on Studio and two on Personal. Split by tier or by date rather than by arbitrary row ranges, and each ZIP maps to something you can actually hand to someone. Every rendered row counts as one render against your monthly pool, so 200 tickets is 200 renders. Renders that fail are refunded automatically, and a batch rejected at validation is never charged, so a failed job costs you time and not quota. There's also a maximum output resolution that varies by plan, so if you're producing large-format passes rather than pocket tickets, check that before you design rather than after. Making the ZIP usable on the day Files in the ZIP are named from your data, which is the reason to have a ticket_number column even if the number never appears prominently on the design. A ZIP of 0001.pdf through 0200.pdf can be matched against your guest list. A ZIP of anonymously named exports cannot. Keep the same CSV as your source of truth. It already has the number, the tier and the verification URL, so if you add an email column it becomes both your send list and your door list, and the files line up with it row for row. When to skip the spreadsheet entirely The batch flow is a human workflow. You sit down, you make 200 tickets, you're done. That fits an event, because events have a date and tickets get made before it. It doesn't fit selling tickets continuously. If a ticket should exist the moment someone pays, at whatever hour that happens, you want the same template called from your backend instead: one POST per purchase carrying that buyer's number and URL, PDF bytes back, attached to the confirmation email. Same template, same variables, nobody at a keyboard. Most event organizers end up using both, because the pre-sale run and the walk-up ticket are genuinely different problems. What this costs A 200-ticket event is 200 renders. The free plan's 100 renders a month covers a small event or a test run of one tier. Beyond that you're on Personal at $29/month for 5,000 renders, which covers a season of events rather than a single one, and manual exports from the editor don't count against it.The batch generation guide covers the dialog step by step, and the template gallery has 13 ticket designs to start from rather than a blank canvas.