What Adobe and Vecteezy Reviewers Actually Check Before They Approve
The first batch I ever submitted got rejected in under four hours.
Not the art. The art was fine. The CSV was wrong. I had built a 15-column metadata file with the right headers for Dreamstime and then uploaded it to Adobe, which wanted 5 columns. Adobe's system did not tell me "wrong header format." It told me my account had a submission error and asked me to review the guidelines. That is a polite way of saying the whole batch was dead on arrival.
I spent the next week reading 300+ pages of contributor documentation, forum threads, and rejection reports, and then I rewrote my pipeline so the same mistake could not happen twice. Here is what I learned about what those platforms actually look for.
The CSV header is the gate, not the artwork
Every one of the three big channels I work with has a fixed metadata schema, and they enforce it at upload time.
Adobe takes 5 columns. Vecteezy takes 4. Dreamstime takes 15, and it wants them in a specific order with specific names. If one header is off by a word, the file is rejected before a human ever sees the image. That is why my make_metadata.py script writes the header first and then refuses to build the rest until the header matches the platform exactly. It takes --platform adobe, --platform vecteezy, or --platform dreamstime and produces the column structure that platform demands. Nothing else gets written.
The other half of metadata review is the title and keywords themselves. A filename title-cased is fine for a first pass and will get you through testing, but real reviewers want titles that describe the asset and keywords that match what buyers type. I learned to keep a titles.json file next to the assets so I could pass --titles titles.json and skip the placeholder names entirely.
Duplicate submissions are how accounts get flagged
Reviewers do not just check the file. They check the history.
If you run your upload batch twice because you are not sure whether it finished, you have now submitted every asset twice. On a small account that is a warning. On a repeat offender it is a suspension. The fastest way to get flagged is not bad art, it is a double post.
I solved this with upload_tracker.py, a ledger that remembers what has already been posted. Before any batch I run pending items.txt to see what is actually left. When something goes up I run done "asset-001.jpg". If I re-run the same source folder, the tracker skips everything already marked done. It uses the standard library, no install, and it has saved me from at least two account-level incidents I know about and probably more I do not.
The files themselves have to look like products
Approval is one gate. A sale is another.
A bare vector file in a zip sells poorly. A zip with a real cover and a matching thumbnail sells. Reviewers do not judge your cover the way a buyer does, but buyers judge it immediately, and the platform's search algorithm weighs click-through. A 1280×720 cover and a 600×600 thumbnail are not optional decoration, they are part of the product.
My pack_product.py script takes a folder and a title, zips the files, and renders both images in one command. It uses Pillow for the covers, which is one of only two third-party packages in the whole kit. The other is reportlab, used by md2pdf.py to turn a Markdown doc into a clean, styled PDF with headings, tables, lists, and links. If you only use the metadata and tracker scripts, you do not install anything at all.
The rule I keep coming back to
Reviewers approve files that match the format exactly, describe themselves accurately, and have not been submitted before. That is it. The artwork is almost secondary to those three things at the review stage, because a rejected file never reaches the point where anyone looks at it.
This is why my whole pipeline is built around constraint, not creativity. make_metadata.py writes only the header the platform demands. upload_tracker.py makes double-posting impossible. pack_product.py produces the cover and thumbnail that the listing needs to compete. Four standalone scripts, no framework, no cloud account, and the entire thing ran on a single-core 2 GB server with no GPU.
That last part matters more than it sounds. The parent project behind this kit generated 856 MB of finished output across 39 products, roughly 19,000 lines of pipeline code, and it never needed a machine bigger than 1 vCPU and 2 GB of RAM. It ran one process at a time, called gc.collect() between items, and measured peak RSS with resource.getrusage(RUSAGE_SELF).ru_maxrss instead of trusting averages. Heavy render steps ran one file per subprocess so memory returned to the OS. None of that is clever. It is just discipline about not asking a small box to do too much at once.
If you are building a catalogue and want the same gate to catch your mistakes before a reviewer does, the four scripts are packaged together.
Building digital products? Free guides & kits for digital product sellers.
Top comments (0)