Where generated XML/PDF files are stored and how to protect them
Goal
Know where documents generated by POP physically end up on the server, and how to prevent them from being publicly downloadable by anyone who knows (or guesses) the URL.
Storage paths
Documents generated through the POP cloud APIs (XML, PDF, and the additional formats UBL, KSeF, ZUGFeRD
depending on the active channel) are cached locally to speed up downloads and reduce API credit
consumption, under wp-content/uploads/, organized by year and month:
wp-content/uploads/pop-xml/YYYY/MM/
wp-content/uploads/pop-pdf/YYYY/MM/
wp-content/uploads/pop-ubl/YYYY/MM/
wp-content/uploads/pop-ksef/YYYY/MM/
wp-content/uploads/pop-zugferd/YYYY/MM/
There’s also a separate, optional setting to save a copy of the generated XML in a dedicated folder
(useful for backups/external integrations): by default wp-content/uploads/pop-invoice, configurable in
Advanced.
Automatic protection (Apache)
Every pop-* folder is automatically protected by POP, which creates an .htaccess file inside it:
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Deny from all
</IfModule>
This blocks direct browser access on Apache servers. The file is generated automatically on the first write to each folder: you don’t need to create it by hand.
Protection on NGINX (requires manual setup)
On NGINX servers (e.g. Kinsta, WPEngine, a VPS running NGINX) .htaccess directives aren’t read: you
need an equivalent rule in the site configuration, for example:
location ~ ^/wp-content/uploads/pop-(pdf|xml|ubl|ksef|zugferd|invoice)/.*$ {
return 403;
}
After adding it, restart NGINX to apply it.
Verify
Try opening the URL of a generated file directly in the browser (e.g.
https://yoursite.com/wp-content/uploads/pop-pdf/2026/07/document.pdf): it should return a 403
(access denied) error, not the file.
Common errors
- The file is publicly downloadable on NGINX — the
.htaccessgenerated by POP has no effect on NGINX: you need the manuallocationrule above, applied by your hosting/provider. - You don’t know whether your hosting uses Apache or NGINX — ask your provider: the difference completely changes the protection method to apply.
- The
pop-invoicefolder is empty — this is normal if you haven’t enabled the optional local storage setting in Advanced: downloads from the Invoices tab still use thepop-xml/pop-pdfcache regardless.
Related configuration
For the format and limits of the generated XML, see xml-invoices-generated.