Reports for clients

Build a PDF or XLSX report of a project's listings under your agency's name, wait until it is ready, and download it within 7 days.

What you'll build

A report to forward to your client: every directory with its status, and the link once a listing is live, prepared under your agency's name. The PDF reads as a document; the XLSX has 1 row per listing for your own sheets. For a client portal of your own, the same data comes from the listings.

Before you start

  • A launched project. A report lists its listings, so a draft has nothing to show.
  • Somewhere to keep the file. Reports are deleted 7 days after they are ready.

1. Build the report

POST /projects/{project_id}/reports starts a report in pdf or xlsx. Each project can start 1 PDF every 30 seconds and 1 XLSX every 10 seconds.

curl https://api.submitator.com/v1/projects/prj_4QzX1m9Lr2Vb7Nc8Tk3HwP/reports \
  -H "Authorization: Bearer $SUBMITATOR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"format": "pdf"}'
Response 202
{
  "object": "report",
  "id": "rep_6Hn2Wq8Lx3Kt9Vb5Rz1MdP",
  "livemode": false,
  "project": "prj_4QzX1m9Lr2Vb7Nc8Tk3HwP",
  "format": "pdf",
  "include_logins": false,
  "status": "building",
  "file_name": null,
  "created_at": "2026-10-08T15:02:10Z",
  "ready_at": null,
  "expires_at": null
}

2. Wait until it is ready

The report moves from building to ready, or to failed. Wait for the report.ready webhook, or read the report every 3 seconds.

curl https://api.submitator.com/v1/reports/rep_6Hn2Wq8Lx3Kt9Vb5Rz1MdP \
  -H "Authorization: Bearer $SUBMITATOR_API_KEY"
Response 200
{
  "object": "report",
  "id": "rep_6Hn2Wq8Lx3Kt9Vb5Rz1MdP",
  "livemode": false,
  "project": "prj_4QzX1m9Lr2Vb7Nc8Tk3HwP",
  "format": "pdf",
  "include_logins": false,
  "status": "ready",
  "file_name": "ledgerly-listings-2026-10-08.pdf",
  "created_at": "2026-10-08T15:02:10Z",
  "ready_at": "2026-10-08T15:02:41Z",
  "expires_at": "2026-10-15T15:02:41Z"
}

A failed report sends report.failed. Build a new one, and write to support with the event's id if it fails again.

3. Download the file

GET /reports/{report_id}/file returns the file itself, with its name in Content-Disposition. Keep a copy: after expires_at the call returns 410 gone.

curl https://api.submitator.com/v1/reports/rep_6Hn2Wq8Lx3Kt9Vb5Rz1MdP/file \
  -H "Authorization: Bearer $SUBMITATOR_API_KEY" \
  -o ledgerly-listings.pdf

The report shows statuses with the labels the console uses: Pending, In progress, Needs you, Submitted, Live, Not accepted and Cancelled. In test mode the file is a sample marked TEST MODE.

4. Or build your own view

For a page in your own portal, read the listings and show what you like. Each live listing has its live_url, and proof_url is a screenshot of it when there is one.

curl "https://api.submitator.com/v1/projects/prj_4QzX1m9Lr2Vb7Nc8Tk3HwP/listings?status=live&limit=100" \
  -H "Authorization: Bearer $SUBMITATOR_API_KEY"
One listing from the response
{
  "object": "listing",
  "id": "lst_7Hk2Qn4Rt9Vx1Bm6Cz3LdK",
  "directory": { "id": "dir_2Lm8Wq3Zk7Rt1Xc5Vb9NdF", "name": "BetaList", "domain_rating": 73 },
  "status": "live",
  "live_url": "https://betalist.com/startups/ledgerly",
  "proof_url": "https://feed.example.net/a/Pf8Kq2Wm.t6Lx9",
  "live_at": "2026-10-08T14:00:00Z"
}

The images in proof_url and the directory logos load from a neutral host with no brand on it, so they can go on your client's page as they are. A Domain Rating you show should credit Ahrefs, which measures it.

5. Include the logins

Some directories need an account to list a product, and we create one there for your client. Send include_logins: true to hand those logins over with the report: the PDF gets a Directory logins page and the XLSX a Logins sheet, with each directory, where to sign in, the email, the username where the directory uses one, and whether the account is ready. Both show the project's one password, which every login uses.

curl https://api.submitator.com/v1/projects/prj_4QzX1m9Lr2Vb7Nc8Tk3HwP/reports \
  -H "Authorization: Bearer $SUBMITATOR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"format": "pdf", "include_logins": true}'
Response 202 (some fields left out)
{
  "object": "report",
  "id": "rep_3Vx8Lm2Qt7Kn5Wb9Rz4HcJ",
  "format": "pdf",
  "include_logins": true,
  "status": "building"
}

Wait for it and download it as in steps 2 and 3. The limits of step 1 count reports with logins separately, so a PDF with logins can start right after a PDF without.

The file holds credentials, so only a key with full permissions and your team in the console can download it: a read-only key gets 403 permission_denied. The page of a share link never offers it, even when it is the newest report, so send the file to your client yourself.

Ask your client to keep the password unchanged while listings are in progress: every account signs in with it. For your own portal, Logins returns the same logins as JSON, and the emails each directory sent to its login, unless they go to your client's own address.

Check it worked

  • GET /reports/rep_6Hn2Wq8Lx3Kt9Vb5Rz1MdP shows status ready and an expires_at 7 days after ready_at.
  • The downloaded file opens, and its rows match GET /projects/prj_4QzX1m9Lr2Vb7Nc8Tk3HwP/listings.

What can go wrong

CodeStatusFix
rate_limited429A report of the same format, with or without logins as this one, started less than 30 seconds (PDF) or 10 seconds (XLSX) ago. Wait the seconds in Retry-After.
not_found404The report is still building, or the id is unknown in this mode.
gone410The file is older than 7 days and was deleted. Build a new report.
validation_failed422format is not pdf or xlsx, or include_logins is not true or false.

Next steps