Badge

Some directories list a product only while their badge shows on the product's site. One feed serves every badge a project needs, under your agency's brand: your client installs it once and new badges appear by themselves.

Get the install kit, forward client_message to your client, then verify. Until the badge is verified, those directories stay out of the launch and appear in readiness.unlocks.

GET
/projects/{project_id}/badge

Returns what your client needs to show the badges on their site: the feed URLs, 6 ready snippets, a command to check the install and a message you can forward. The feed serves every badge the project needs under your agency's brand, so your client installs it once.

Path Parameters

project_id*string

The project's id.

Match^prj_[0-9A-Za-z]{22}$

Response Body

The install kit and the result of the last check.

application/json
  1. response

The badge install kit for one project and the result of its last check.

object*string

Always badge.

livemode*boolean

true for a live project, false for a test project.

project*string

The project's id.

Match^prj_[0-9A-Za-z]{22}$
status*string

not_checked until the first check, then installed or not_found.

Value in"not_checked""installed""not_found"
checked_at*|

When the site was last checked. null before the first check.

Formatdate-time
feed*|

Where the project's badges are served; a response can be cached for 60 seconds. null while the feed is not available yet.

recipes*array<>

Ready snippets that place the badges in a page, 1 per kind of site.

check_command*string

A command that prints how many badge links the site's home page shows, following its redirects as our check does. 0 means the install is not live.

client_message*string

A message you can forward to your client as it is. It names no one but the product.

Typical errors

curl "https://api.submitator.com/v1/projects/prj_4QzX1m9Lr2Vb7Nc8Tk3HwP/badge" \  -H "Authorization: Bearer $SUBMITATOR_API_KEY"
{  "object": "badge",  "livemode": false,  "project": "prj_4QzX1m9Lr2Vb7Nc8Tk3HwP",  "status": "not_found",  "checked_at": "2026-10-08T09:12:44Z",  "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": "nextjs",      "title": "Next.js (App Router)",      "language": "tsx",      "code": "// app/directory-badges.tsx: render <DirectoryBadges /> in your footer\nexport default async function DirectoryBadges() {\n  try {\n    const res = await fetch(\"https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.json\", {\n      next: { revalidate: 300 },\n    });\n    if (!res.ok) return null;\n    const { badges } = await res.json();\n    return <div dangerouslySetInnerHTML={{ __html: badges.join(\"\") }} />;\n  } catch {\n    return null;\n  }\n}"    },    {      "platform": "php",      "title": "PHP",      "language": "php",      "code": "<?php\n// Put this where the badges should appear, for example in footer.php\n$context = stream_context_create([\"http\" => [\"timeout\" => 3]]);\n$badges = @file_get_contents(\"https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.html\", false, $context);\nif ($badges !== false && strpos($http_response_header[0] ?? \"\", \" 200 \") !== false) {\n  echo $badges;\n}"    },    {      "platform": "wordpress",      "title": "WordPress",      "language": "php",      "code": "// functions.php: then add the [directory_badges] shortcode to your footer\nadd_shortcode(\"directory_badges\", function () {\n  $response = wp_remote_get(\"https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.html\", [\"timeout\" => 3]);\n  if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {\n    return \"\";\n  }\n  return wp_remote_retrieve_body($response);\n});"    },    {      "platform": "nginx_ssi",      "title": "nginx with SSI",      "language": "nginx",      "code": "# In the server block of ledgerly.test\nlocation = /directory-badges {\n  internal;\n  proxy_pass https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.html;\n  proxy_ssl_server_name on;\n  proxy_set_header Accept-Encoding \"\";\n}\n\n# In the location that serves your pages\nssi on;\n\n# In the page, where the badges should appear:\n# <!--# include virtual=\"/directory-badges\" -->"    },    {      "platform": "html",      "title": "Static site",      "language": "shell",      "code": "# Run before each deploy, then include the file in your footer\ncurl -fsS https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.html -o partials/directory-badges.html"    },    {      "platform": "ai_prompt",      "title": "Prompt for an AI coding tool",      "language": "text",      "code": "Add a server-rendered block to the footer of every page of my site. When the page is built or requested, fetch https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.html with a 3 second timeout. If the response status is 200, insert the returned HTML as it is. On any other status or error, render nothing. Do not load it with client-side JavaScript: the badges must be in the HTML the server sends."    }  ],  "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."}

Verify the badge

POST
/projects/{project_id}/badge/verify

Reads the project's site now and looks for the badge. Call it after your client installs the snippet: once it passes, directories that need the badge open to the project and auto-replace can add them. You can verify a project 10 times per hour.

Path Parameters

project_id*string

The project's id.

Match^prj_[0-9A-Za-z]{22}$

Response Body

The badge is on the site.

application/json
  1. response

The badge install kit for one project and the result of its last check.

object*string

Always badge.

livemode*boolean

true for a live project, false for a test project.

project*string

The project's id.

Match^prj_[0-9A-Za-z]{22}$
status*string

not_checked until the first check, then installed or not_found.

Value in"not_checked""installed""not_found"
checked_at*|

When the site was last checked. null before the first check.

Formatdate-time
feed*|

Where the project's badges are served; a response can be cached for 60 seconds. null while the feed is not available yet.

recipes*array<>

Ready snippets that place the badges in a page, 1 per kind of site.

check_command*string

A command that prints how many badge links the site's home page shows, following its redirects as our check does. 0 means the install is not live.

client_message*string

A message you can forward to your client as it is. It names no one but the product.

curl -X POST "https://api.submitator.com/v1/projects/prj_4QzX1m9Lr2Vb7Nc8Tk3HwP/badge/verify" \  -H "Authorization: Bearer $SUBMITATOR_API_KEY"
{  "object": "badge",  "livemode": false,  "project": "prj_4QzX1m9Lr2Vb7Nc8Tk3HwP",  "status": "installed",  "checked_at": "2026-10-04T09:58:03Z",  "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": "nextjs",      "title": "Next.js (App Router)",      "language": "tsx",      "code": "// app/directory-badges.tsx: render <DirectoryBadges /> in your footer\nexport default async function DirectoryBadges() {\n  try {\n    const res = await fetch(\"https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.json\", {\n      next: { revalidate: 300 },\n    });\n    if (!res.ok) return null;\n    const { badges } = await res.json();\n    return <div dangerouslySetInnerHTML={{ __html: badges.join(\"\") }} />;\n  } catch {\n    return null;\n  }\n}"    },    {      "platform": "php",      "title": "PHP",      "language": "php",      "code": "<?php\n// Put this where the badges should appear, for example in footer.php\n$context = stream_context_create([\"http\" => [\"timeout\" => 3]]);\n$badges = @file_get_contents(\"https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.html\", false, $context);\nif ($badges !== false && strpos($http_response_header[0] ?? \"\", \" 200 \") !== false) {\n  echo $badges;\n}"    },    {      "platform": "wordpress",      "title": "WordPress",      "language": "php",      "code": "// functions.php: then add the [directory_badges] shortcode to your footer\nadd_shortcode(\"directory_badges\", function () {\n  $response = wp_remote_get(\"https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.html\", [\"timeout\" => 3]);\n  if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {\n    return \"\";\n  }\n  return wp_remote_retrieve_body($response);\n});"    },    {      "platform": "nginx_ssi",      "title": "nginx with SSI",      "language": "nginx",      "code": "# In the server block of ledgerly.test\nlocation = /directory-badges {\n  internal;\n  proxy_pass https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.html;\n  proxy_ssl_server_name on;\n  proxy_set_header Accept-Encoding \"\";\n}\n\n# In the location that serves your pages\nssi on;\n\n# In the page, where the badges should appear:\n# <!--# include virtual=\"/directory-badges\" -->"    },    {      "platform": "html",      "title": "Static site",      "language": "shell",      "code": "# Run before each deploy, then include the file in your footer\ncurl -fsS https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.html -o partials/directory-badges.html"    },    {      "platform": "ai_prompt",      "title": "Prompt for an AI coding tool",      "language": "text",      "code": "Add a server-rendered block to the footer of every page of my site. When the page is built or requested, fetch https://feed.example.net/badge/91bb683b-04df-68e5-fea1-c01f13987d91.html with a 3 second timeout. If the response status is 200, insert the returned HTML as it is. On any other status or error, render nothing. Do not load it with client-side JavaScript: the badges must be in the HTML the server sends."    }  ],  "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."}