# Badge

URL: https://submitator.com/docs/api/badge

> Some directories list a product only while their badge shows on the product's site.

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 the badge install kit

`GET https://api.submitator.com/v1/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.

| Parameter | In | Required | What it is |
| --- | --- | --- | --- |
| `project_id` | path | Yes | The project's id. |

Response 200:

```json
{
  "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."
}
```

Typical errors: [`not_found`](https://submitator.com/docs/errors#not_found), [`rate_limited`](https://submitator.com/docs/errors#rate_limited).

## Verify the badge

`POST https://api.submitator.com/v1/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.

| Parameter | In | Required | What it is |
| --- | --- | --- | --- |
| `project_id` | path | Yes | The project's id. |

Response 200:

```json
{
  "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."
}
```

Typical errors: [`badge_not_found`](https://submitator.com/docs/errors#badge_not_found), [`rate_limited`](https://submitator.com/docs/errors#rate_limited).
