What is SFTP?
SFTP (SSH File Transfer Protocol) is a standard way to move files securely between your systems and Daylit over the internet. You export data from your source system as CSV files, then upload them to a Daylit-managed endpoint on a schedule you control. Authentication uses SSH keys — not passwords — so automated jobs can run unattended. Once files land, Daylit validates them against your field mapping, ingests the records, and keeps your AR dashboard current through incremental delta uploads.Why SFTP?
Most Daylit customers connect their accounting system through Merge — an OAuth link to QuickBooks, NetSuite, Xero, Sage, or another Merge-supported platform. Data syncs automatically with no file exports on your side. SFTP is the right path when a direct connection isn’t possible or practical:- Your system isn’t supported by Merge. Legacy ERPs, industry-specific billing platforms, or custom-built tools often aren’t available for OAuth linking.
- Your IT or security team restricts API access. Some organizations block third-party connections to accounting systems but allow scheduled file drops to an approved endpoint.
- You already export data on a schedule. If your ERP produces nightly CSV reports or you run SQL exports from a data warehouse, SFTP plugs into that existing workflow.
- You need to combine data from multiple sources. You can merge customers, invoices, and contacts from different systems into unified files before uploading.
- You want explicit control over what Daylit receives. You choose exactly which fields and records leave your environment, and when.
If your accounting platform appears in the Merge provider list, a direct integration is usually faster to set up. Use this SFTP guide when your Daylit contact directs you here or when OAuth linking isn’t an option.
Before you start
What you’ll need
- An export from your source system. Daylit accepts CSV files. Most ERPs, accounting systems, and billing platforms can produce scheduled exports or report-to-file output.
- A machine that can run an SFTP client. Use the command line (
sftpon macOS, Linux, and modern Windows) or a GUI tool such as FileZilla, WinSCP, or Cyberduck. - A place to run a scheduled job. Eventually you want uploads on a schedule — cron, Windows Task Scheduler, Airflow, or your ERP’s built-in scheduler.
- About 30 minutes to reach your first validated sample upload. A full snapshot adds another ~20 minutes depending on volume.
- One technical contact. Daylit emails this address when something needs your attention.
What you won’t need
- A VPN or special network access. Standard internet over port 22 is enough.
- A password. Daylit uses SSH keys only — more secure and easier to automate.
- A waiting period on Daylit’s side. Everything in this guide is self-serve in the portal, though Daylit support is available if you need help.
Quick start
If you’ve done SFTP integrations before, here’s the speed run. Details follow in the steps below.Register the public key
Sign in to Daylit, go to Settings → SFTP Connection → Endpoints, and paste the contents of
~/.ssh/daylit_ed25519.pub. Give the connection a name (for example, primary-source).Map your columns
On the Mapping tab, map your source columns to Daylit’s canonical fields for each object.
Copy connection details
After saving, copy the hostname, port, and system-generated username from your connection card.
Upload a sample
sftp -i ~/.ssh/daylit_ed25519 username@sftp.daylit.com and put a sample file into /sample/{object}/.Step 1 — Generate your SSH key
An SSH key is a matched pair of files that proves your identity without a password. You generate them yourself and keep the private key secure. You’ll register the public key with Daylit in Step 2.~/.ssh/daylit_ed25519— the private key. Never share, email, or commit this file.~/.ssh/daylit_ed25519.pub— the public key. Safe to share with Daylit.
Daylit accepts ED25519, ECDSA, and RSA (3072 bits or larger). ED25519 is the modern default. Use
ssh-keygen -t rsa -b 4096 if your environment requires RSA.ssh-ed25519 (or ssh-rsa), followed by base64, then your comment:
-----BEGIN OPENSSH PRIVATE KEY-----, you’re looking at the private key. Don’t paste that into the portal.
Estimated time: 5 minutes.
Step 2 — Register the public key in Daylit
Sign in at intelligence.daylit.com. If you don’t have access yet, request it from your Daylit contact. Then:- Open your public key file in a text editor and copy the entire single line.
- Go to Settings → SFTP Connection → Endpoints.
- Paste the public key into the SSH Public Key field.
- Enter a Connection Name (for example,
sage-exportorprimary-source) so you can identify which system the data comes from. Use lowercase letters, digits, and hyphens. - Click Save configuration.
Step 3 — Get your connection details
After you save your endpoint, Daylit creates your SFTP user, private storage area, and access scope. Your connection card shows:- SFTP Hostname / Endpoint —
sftp.daylit.com - Port —
22(standard SFTP) - Assigned Username — system-generated for this connection
- Key updated at — timestamp of the latest key rotation for this connection
Optional: SSH config entry
For command-line use, add an entry to~/.ssh/config:
chmod 600 ~/.ssh/config ~/.ssh/daylit_ed25519. After that, you can connect with sftp daylit instead of typing the full command sftp -i ~/.ssh/daylit_ed25519 your-username@sftp.daylit.com each time. The SSH config entry supplies your hostname, username, port, and key automatically.
Upload paths
Daylit creates these top-level directories for your workspace:| Path | Purpose |
|---|---|
/test/ | Connectivity check only — no business validation |
/sample/ | Small files (≤ 100 rows) to validate your mapping |
/init/ | Full snapshot of every record in an object |
/delta/ | Incremental updates since your last successful upload |
/sample/invoice/). See SFTP data schema for the full path structure.
Test your connection
Connect to your SFTP workspace with one of these commands:/test/ and exit:
Step 4 — Get your data prepared
Daylit requires five objects before you can go live:| Object | What it is |
|---|---|
| Customer | Companies or individuals you bill |
| Customer Contact | AP and billing contacts at each customer |
| Invoice | Invoices with amounts, dates, status, and embedded payment info |
| Credit Note | Refunds, returns, and applied or unapplied credits |
| Payment | Individual payment events, one row per invoice allocation |
Step 5 — Map your columns to Daylit fields
Daylit uses a canonical schema — a fixed set of field names per object (for example, every invoice hasremote_id, customer_remote_id, total_amount, issue_date). Your source system likely uses different column names. The mapping tells Daylit how to translate.
For each object, the Mapping tab shows three columns: Daylit field (fixed), External parameter name, and Format.
Enter the corresponding parameter name from your data for each Daylit field, then select the correct format. Be especially careful with date fields — the format must match how your export represents dates (for example, MM/DD/YYYY vs YYYY-MM-DD).
Step 6 — Upload and validate your sample
A sample proves your mapping is correct before you send data at scale. Daylit validates the sample but does not ingest it into production.Produce the sample
Export 10–100 representative rows for one object from your source system. Include a mix of customers, statuses, and edge cases — not all rows from one customer.Upload
Command line:Validate in the portal
Go to Settings → SFTP Connection → Sample Checks, select your SFTP connection, and click Validate for each object (or Validate all). Pass — all rows parsed with zero errors. Move on to the next object. Fail — the report shows row-level errors in plain language: Common sample failures:- Date format mismatch — update the format in Mapping, save, and click Validate again. You don’t need to re-upload unless you want to test a new file.
- Currency symbol or thousands separator in an amount column — add the
decimaltransform. - Empty required field — map the field to the correct source column or fix the export.
Step 7 — Upload your init (full snapshot)
Once every sample passes, send your first init — a complete snapshot of every record in the object. You usually do this once per object; future updates are deltas.Produce the init
Run the same export as your sample, but with no row limit:- Customer — every active customer (inactive optional)
- Customer Contact — customer ID, contact ID, and email
- Invoice — every invoice: open, partially paid, paid, voided, and draft
- Credit Note — every credit note, applied or unapplied
- Payment — every payment event, one row per invoice allocation (optional)
Upload order
Upload parents before children so foreign keys resolve immediately:/init/customer/first/init/customer_contact/and/or/init/invoice/next/init/credit_note/and/or/init/payment/
Dry-run and apply
After upload, click Dry-run in the portal to generate a report and preview how your data will look. Start with the Customer object first, then proceed in dependency order. Fix any validation errors before moving on. When the dry-run is clean, click Apply to ingest the data. Large inits may take time to complete.If validation fails, the init is rejected as a unit — Daylit doesn’t write half of a snapshot. You see exactly what failed and re-upload after fixing. We again take the latest upload file for init check, or you can replace the original file.A single wrong row will invalidate the whole batch. This is initial batch hence we need to ensure the data is correct.
Step 8 — Set up your delta schedule
After your init is applied, keep Daylit current with deltas — incremental files containing every record created or modified since your last successful upload.What a delta should contain
Filter exports by your source system’s “last modified” timestamp:How often to run
Daylit picks up new files every 15 minutes, so running more frequently than that doesn’t speed ingestion. Common cadences:- Hourly — active collections and AR aging workflows
- Nightly — when 24-hour freshness is sufficient
- Every 15 minutes — high-priority objects like invoices
Scheduling the upload
- Linux / macOS cron
- Airflow / Prefect / Dagster
- Built-in ERP scheduler
Add to your crontab (A minimal A few things this script does on purpose:
crontab -e):daylit_delta.sh:- It uses a
last_run.txtfile to remember when the last successful run was, so the next delta picks up from there. Don’t use “the last 24 hours” — if a run fails, you’d miss data permanently. - It only updates
last_run.txtafter the upload succeeds. If the SFTP step fails, the next run re-tries from the same starting point. set -euo pipefailmakes the script fail loudly on any error rather than silently producing an empty file.StrictHostKeyChecking=yesensures the host key is verified.
Reference
The numbered steps above walk you through initial SFTP onboarding. The sections below cover ongoing maintenance, troubleshooting, and quick lookup — they are not part of the setup flow.Rotate your SSH key
Rotate every 6–12 months, or when someone with access to your private key leaves the team:- Generate a new key:
ssh-keygen -t ed25519 -f ~/.ssh/daylit_ed25519_new - In Settings → SFTP Connection → Endpoints, add the new public key.
- Test:
sftp -i ~/.ssh/daylit_ed25519_new your-username@sftp.daylit.com - Update your scheduled job to use the new key and run it once manually.
- Remove the old public key from the portal and delete the old private key from disk.
Troubleshooting
Permission denied (publickey)
Permission denied (publickey)
Your SFTP client is presenting the wrong key, or the key isn’t registered in the portal.
- Confirm you’re using
-i ~/.ssh/daylit_ed25519(path to the private key). - Verify the matching public key appears under Settings → SFTP Connection → Endpoints.
- Confirm the username matches your connection card exactly.
Host key verification failed
Host key verification failed
Compare the fingerprint your client shows against the value in the portal. If they match, accept the new key. If they don’t, stop and contact support@daylit.com.
Sample failed: column not found
Sample failed: column not found
Your CSV doesn’t have a column your mapping references. Re-check the export query and your mapping on the Mapping tab.
Init failed: foreign key not resolved
Init failed: foreign key not resolved
A child record references a parent that isn’t in the init. Upload the customer init first, and confirm customer ID columns match across exports (for example,
client_id vs account_id).Delta failed: remote_updated_at went backwards
Delta failed: remote_updated_at went backwards
A record’s
remote_updated_at is older than the version Daylit already has. Verify your export uses the same timestamp column as your mapping.Scheduled job silently failing
Scheduled job silently failing
Use
set -euo pipefail in your script so SFTP failures exit non-zero. Log stderr and configure your scheduler to alert on failure.FAQ
Can I use a password instead of an SSH key?
Can I use a password instead of an SSH key?
No. Daylit accepts SSH keys only (ED25519, ECDSA, or RSA ≥ 3072 bits). Keys are more secure and easier to automate.
What if my ERP can't produce CSV?
What if my ERP can't produce CSV?
Try formatting to CSV export. A small middleware script (SQL query → file) usually solves export limitations. More file format options are coming soon. Contact Daylit to scope a solution.
Can I send the same data twice?
Can I send the same data twice?
Yes. Daylit upserts on
remote_id — duplicate sends update existing rows rather than creating duplicates.Can I have separate test and production environments?
Can I have separate test and production environments?
Yes. Create a second workspace and run your scheduled job against test first. Point at production once you’re satisfied.
Where is my data stored?
Where is my data stored?
Your files are encrypted at rest and in transit when you upload via SFTP. We never share your data with other clients. The ingestion pipeline is read-only into Daylit; we do not write back to your source system.
Glossary
| Term | Definition |
|---|---|
| Canonical schema | Daylit’s fixed field names per object. Your mapping translates source column names to these fields. |
| Sample | A small file that validates your mapping. Not ingested into production. |
| Init | A full snapshot of every record in an object. Sent once as the starting state. |
| Delta | An incremental update with records created or modified since the last successful upload. |
| remote_id | The record’s identifier in your source system. Required on every row. Daylit upserts on this value. |
| Upsert | Insert if remote_id is new; update if it’s already known. |
Getting help
- Portal in-app chat — bottom-right on every page.
- Email: support@daylit.com. Include your workspace name and the filename or timestamp you’re asking about.
- Status page: status.daylit.com for any active incidents.