Try it in this demo
A scheduled import fetches the same file again and again (every hour, day or week) and imports it with the columns, clean-up and value mapping of an import you did once by hand. The sample below, "Supplier price list", fetches supplier-prices.csv from storage every day at 06:00.
- Press "Run now" on the sample. The supplier's new prices are checked and imported in the background; "Last run" shows the result (reload the page while it says it is importing).
- Open Products: Blue pen (SKU-00001) now costs 1,350, and Brand new mug and Garden hose have been added.
- Make your own: import products.csv on Products, press "Run on a schedule…" on the result, choose "In storage" and pick supplier-prices.csv.
Where the file comes from, and how it works
A scheduled import fetches the file again on every run, from a link or from storage, and imports it with the settings of the first import.
1. Turn it on
Add ->schedules() to the import action. After an import, the result offers "Run on a schedule…", where users name the schedule, say where the file is and how often to run it.
use App\Import\Filament\Imports\ProductImporter;
use Qalainau\FilamentWarpImport\Actions\WarpImportAction;
protected function getHeaderActions(): array
{
return [
WarpImportAction::make()
->importer(ProductImporter::class)
->schedules(
// Who may create schedules (default: true)
condition: fn (): bool => auth()->user()->isAdmin(),
// Laravel disks users may pick files from ([] = links only)
disks: ['supplier'],
// Allow links: http, https and Google Sheets share links
urls: true,
// Allow links to 127.0.0.1, 10.x, 192.168.x and other internal addresses
privateNetwork: false,
),
];
}
2. From a link
Choose "At a link" and paste the address of a CSV or Excel file. A Google Sheets share link is fetched as its CSV export; share the spreadsheet with anyone who has the link. Only http and https are allowed, and links to internal network addresses are refused, also where a redirect leads.
# A CSV or Excel file on the web
https://supplier.example.com/feeds/prices.csv
https://supplier.example.com/feeds/stock.xlsx
# A Google Sheets share link (the tab in #gid) …
https://docs.google.com/spreadsheets/d/1AbCdEfGhIjKlMnOpQrStUv/edit#gid=0
# … is fetched as its CSV export
https://docs.google.com/spreadsheets/d/1AbCdEfGhIjKlMnOpQrStUv/export?format=csv&gid=0
# Refused: internal network addresses
http://192.168.1.20/prices.csv
3. From storage
Choose "In storage": the .csv, .tsv, .txt and .xlsx files on the disks you listed are offered. A disk is any Laravel filesystem disk, so your supplier can upload to an SFTP server or an S3 bucket. List a disk that holds import files only: everyone who may create schedules sees its file names.
// config/filesystems.php
'disks' => [
// An SFTP server your supplier uploads to
// composer require league/flysystem-sftp-v3 "^3.0"
'supplier' => [
'driver' => 'sftp',
'host' => env('SUPPLIER_SFTP_HOST'),
'username' => env('SUPPLIER_SFTP_USERNAME'),
'password' => env('SUPPLIER_SFTP_PASSWORD'),
'root' => '/outgoing',
],
// Or an S3 bucket
// composer require league/flysystem-aws-s3-v3 "^3.0"
'supplier-s3' => [
'driver' => 's3',
'key' => env('SUPPLIER_AWS_ACCESS_KEY_ID'),
'secret' => env('SUPPLIER_AWS_SECRET_ACCESS_KEY'),
'region' => env('SUPPLIER_AWS_DEFAULT_REGION'),
'bucket' => env('SUPPLIER_AWS_BUCKET'),
],
],
// The import action: ->schedules(disks: ['supplier', 'supplier-s3'])
4. In this demo
Storage only. The "supplier" disk is a folder on the demo server, and the demo puts supplier-prices.csv in it. Links are turned off because the demo is public.
// app/Providers/Filament/DemoPanelProvider.php: a folder on the demo server
config(['filesystems.disks.supplier' => [
'driver' => 'local',
'root' => storage_path('app/supplier'),
]]);
// app/Filament/Resources/Products/Pages/ListProducts.php
WarpImportAction::make()
->importer(ProductImporter::class)
->schedules(disks: ['supplier'], urls: false),
5. Each run
CSV, TSV, text or .xlsx (the first sheet), UTF-8, UTF-16 or Shift_JIS, up to 100 MB. Columns are matched by their header names, so another order or extra columns still work. If a mapped header is gone, the run fails and names it. Rows with errors stop the run, or are skipped if you chose so.
# The headers of the first import
SKU,Product name,Category,Price,Stock,Active,Released
# Still imported: another order, an extra column
Price,SKU,Product name,Notes,Category,Stock,Active,Released
# Fails and names "Price": a mapped header is gone
SKU,Product name,Category,Stock,Active,Released
6. On your server
Warp adds warp-import:run-schedules to Laravel's scheduler, every minute. You need the usual cron entry and a queue worker. Nothing runs while a schedule is paused.
# crontab -e: Laravel's scheduler, every minute
* * * * * cd /path-to-your-app && php artisan schedule:run >> /dev/null 2>&1
# A queue worker for the runs (Supervisor, Forge, Ploi …)
php artisan queue:work
# Run the schedules that are due now, by hand
php artisan warp-import:run-schedules
| Name | When | Last run | |
|---|---|---|---|
|
Supplier price list supplier: supplier-prices.csv |
Every day at 06:00 (UTC) Next: Nov 4, 2026 6:00 AM |
— |
|