Install the badge

Some directories list a product only while their badge is on its site. Get the install kit, forward it to your client, check the install and verify it.

What you'll build

One block in the footer of your client's site that shows your agency's badge and every directory badge the project needs, under your brand. Once it is verified, the directories that ask for a badge open to the project. The block updates by itself, so your client installs it once.

Before you start

  • A project. The badge can go up before or after the launch.
  • Someone who can change the site: your client's developer, or you. The last section of this page is a note to forward to them.

1. See what the badge unlocks

Before the launch, the readiness preview counts the directories that wait for the badge. After it, those listings show action_required with action.code install_badge.

curl https://api.submitator.com/v1/projects/prj_4QzX1m9Lr2Vb7Nc8Tk3HwP/readiness \
  -H "Authorization: Bearer $SUBMITATOR_API_KEY"
unlocks from the response
[{ "requirement": "badge", "directories": 9, "how": "Install the badge on https://ledgerly.test and verify it." }]

2. Get the install kit

GET /projects/{project_id}/badge returns the feed URLs, 6 ready snippets, a command that checks the install and a message to forward.

curl https://api.submitator.com/v1/projects/prj_4QzX1m9Lr2Vb7Nc8Tk3HwP/badge \
  -H "Authorization: Bearer $SUBMITATOR_API_KEY"
Response 200 (recipes cut to 1)
{
  "object": "badge",
  "project": "prj_4QzX1m9Lr2Vb7Nc8Tk3HwP",
  "status": "not_checked",
  "checked_at": null,
  "feed": {
    "json_url": "https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.json",
    "html_url": "https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.html"
  },
  "recipes": [
    {
      "platform": "html",
      "title": "Static site",
      "language": "shell",
      "code": "curl -fsS https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.html -o partials/directory-badges.html"
    }
  ],
  "check_command": "curl -sL https://ledgerly.test | grep -c 'ref=91bb683b-04df-68e5-fea1-c01f13987d91'",
  "client_message": "Please add the directory badges block to the footer of https://ledgerly.test. Some directories list Ledgerly only while their badge shows on the site, and the block keeps those badges up to date by itself. Your developer can pick a ready snippet for Next.js, PHP, WordPress, nginx or a static site."
}

The recipes cover nextjs, php, wordpress, nginx_ssi, html for a static site, and ai_prompt, a prompt for an AI coding tool. Each has a title for a tab and the project's feed URL already in its code.

3. Forward it to your client

Send client_message as it is, with the recipe for your client's site and the note at the end of this page. The message names the product and nobody else, so it reads as yours.

In test mode the feed URLs have the right shape but return 404, so a recipe renders nothing there.

4. Check the install

Once the block is up, check_command prints how many badge links the site's home page shows, following redirects as our check does.

curl -sL https://ledgerly.test | grep -c 'ref=91bb683b-04df-68e5-fea1-c01f13987d91'

0 means the badges are not in the HTML the site serves. The usual cause is a block loaded in the browser with JavaScript, which the check does not run.

5. Verify it

POST /projects/{project_id}/badge/verify reads the site now and looks for the badge. You can verify a project 10 times per hour.

curl -X POST https://api.submitator.com/v1/projects/prj_4QzX1m9Lr2Vb7Nc8Tk3HwP/badge/verify \
  -H "Authorization: Bearer $SUBMITATOR_API_KEY"
Response 200 (some fields left out)
{
  "object": "badge",
  "project": "prj_4QzX1m9Lr2Vb7Nc8Tk3HwP",
  "status": "installed",
  "checked_at": "2026-10-04T09:58:03Z"
}

A badge that is not on the site returns 422 badge_not_found: run check_command, fix the install and verify again.

6. What happens next

Once the badge is verified, the directories that need it open to the project. With auto_replace on, they are added from the free allowance by themselves, and the listings that waited in action_required move on. With it off, add them with POST /projects/{project_id}/listings.

Keep the block on the site. Directories that list a product only while their badge shows can take the listing down when it goes.

Check it worked

  • GET /projects/prj_4QzX1m9Lr2Vb7Nc8Tk3HwP/badge shows status installed.
  • The readiness preview no longer lists badge in unlocks.
  • Listings with action.code install_badge move to in_progress, and their listing.in_progress events arrive.

What can go wrong

CodeStatusFix
badge_not_found422The site does not show the badge. Run check_command, fix the install, verify again. In test mode, a host that starts with nobadge. never passes.
rate_limited429More than 10 checks this hour for the project. Wait the seconds in Retry-After.
not_found404The project id belongs to the other mode, or to no project.

A note for your client's developer

Forward this section as it is.

The badge block holds small badges, each an image link. Some directories keep a listing only while their badge shows on the site, and the block keeps the set current by itself: new badges appear without a change on your side.

  • Put it in the footer of every page, or at least of the home page.
  • Render it on the server. The badges must be in the HTML your server sends: a block loaded with client-side JavaScript is not seen. Every snippet does it this way.
  • Never let it break the page. Fetch the feed with a timeout of 3 seconds or less, and render nothing on an error or any status other than 200. The snippets do both.
  • Keep the links as the feed sends them. Each badge links to its directory, and the ref= in the links is how the install is checked.
  • Cache it if you like. A response can be cached for 60 seconds; the Next.js snippet refreshes every 5 minutes.

To check the install, run the check_command you were sent: any number above 0 means the badges are live on the page.

Next steps