{"id":1116,"date":"2026-05-18T13:00:00","date_gmt":"2026-05-18T18:00:00","guid":{"rendered":"https:\/\/tolinku.com\/blog\/?p=1116"},"modified":"2026-03-07T03:34:44","modified_gmt":"2026-03-07T08:34:44","slug":"webhook-security-signing","status":"publish","type":"post","link":"https:\/\/tolinku.com\/blog\/webhook-security-signing\/","title":{"rendered":"Webhook Security: Signing and Verification"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Webhooks are one of the most useful patterns in modern API design. They let your deep linking platform push events to your server in real time: clicks, installs, conversions, referral completions. But there is a problem. A webhook endpoint is just a URL that accepts POST requests. Without proper security, anyone who discovers that URL can send fabricated events to your server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine an attacker sending fake conversion events to your webhook receiver. Your system credits referral rewards that were never earned, updates analytics with phantom data, or triggers automation workflows based on events that never happened. This is not a theoretical risk. Webhook spoofing is a <a href=\"https:\/\/owasp.org\/www-project-web-security-testing-guide\/latest\/4-Web_Application_Security_Testing\/10-Business_Logic_Testing\/\" rel=\"nofollow noopener\" target=\"_blank\">well-documented attack vector<\/a>, and the consequences range from corrupted data to financial loss.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This article covers how webhook security signing works, how to verify signatures in your code, and how to layer additional protections against replay attacks and unauthorized access. If you are building <a href=\"https:\/\/tolinku.com\/blog\/webhooks-integrations-deep-linking\/\">webhook integrations for deep linking<\/a>, this is essential reading.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><img decoding=\"async\" src=\"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/platform-webhooks.png\" alt=\"Tolinku webhook configuration for event notifications\">\n<em>The webhooks page with create form, webhook list, and delivery log.<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why Webhook Security Matters<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When you register a webhook endpoint with a platform like <a href=\"https:\/\/tolinku.com\/features\/webhooks\">Tolinku<\/a>, you are creating a trust relationship. The platform promises to send legitimate event data to your URL. Your server promises to process it and respond with a status code. But HTTP alone does not enforce that trust.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Without signature verification, your webhook receiver has no way to answer a fundamental question: did this request actually come from the platform, or did someone else send it?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The risks break down into three categories:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Spoofed events.<\/strong> An attacker crafts a POST request that looks like a legitimate webhook payload and sends it to your endpoint. If your server blindly trusts the request body, it processes the fake event as real.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Tampered payloads.<\/strong> A man-in-the-middle intercepts a legitimate webhook in transit and modifies the payload before it reaches your server. The event is real, but the data has been altered.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Replay attacks.<\/strong> An attacker captures a legitimate, signed webhook request and resends it minutes, hours, or days later. The signature is valid because the payload has not changed, but the event is being processed a second time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">HMAC signing addresses all three of these risks.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How HMAC-SHA256 Signing Works<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/SubtleCrypto\/sign#hmac\" rel=\"nofollow noopener\" target=\"_blank\">HMAC<\/a> (Hash-based Message Authentication Code) is a cryptographic mechanism for verifying both the integrity and authenticity of a message. When applied to webhooks, the process works like this:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>When you create a webhook endpoint, the platform generates a shared secret. Only you and the platform know this secret.<\/li>\n<li>When the platform sends a webhook, it computes an HMAC-SHA256 hash of the request body using the shared secret as the key.<\/li>\n<li>The platform includes the resulting signature in a request header (typically <code>X-Webhook-Signature<\/code> or similar).<\/li>\n<li>Your server receives the request, computes its own HMAC-SHA256 hash of the request body using the same shared secret, and compares the result to the signature in the header.<\/li>\n<li>If the signatures match, the request is authentic and unmodified. If they do not match, the request was either forged or tampered with.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">The critical property of HMAC is that you cannot compute a valid signature without knowing the secret. An attacker who intercepts a webhook can see the payload and the signature, but they cannot forge a new signature for a different payload without the secret key.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here is a simplified diagram of the flow:<\/p>\n\n\n\n<pre><code>Platform                              Your Server\n   |                                      |\n   |-- Compute HMAC(secret, body) -------&gt;|\n   |-- Send POST with signature header --&gt;|\n   |                                      |-- Compute HMAC(secret, body)\n   |                                      |-- Compare signatures\n   |                                      |-- Accept or reject\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The <a href=\"https:\/\/www.rfc-editor.org\/rfc\/rfc2104\" rel=\"nofollow noopener\" target=\"_blank\">RFC 2104<\/a> specification defines HMAC. SHA-256 is the hash function used in most modern implementations because it provides a strong balance of security and performance.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verifying Webhook Signatures in Node.js<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Here is a complete example of verifying webhook signatures in an Express application. This implementation covers the essentials: extracting the signature header, computing the expected signature, and using a timing-safe comparison.<\/p>\n\n\n\n<pre><code class=\"language-javascript\">const crypto = require(&#39;crypto&#39;);\nconst express = require(&#39;express&#39;);\n\nconst app = express();\n\n\/\/ Important: use raw body for signature verification.\n\/\/ JSON parsing alters whitespace and key order, which\n\/\/ changes the hash.\napp.use(&#39;\/webhooks&#39;, express.raw({ type: &#39;application\/json&#39; }));\n\nconst WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;\n\nfunction verifySignature(payload, signatureHeader) {\n  if (!signatureHeader) {\n    return false;\n  }\n\n  const expectedSignature = crypto\n    .createHmac(&#39;sha256&#39;, WEBHOOK_SECRET)\n    .update(payload)\n    .digest(&#39;hex&#39;);\n\n  \/\/ Use timingSafeEqual to prevent timing attacks.\n  \/\/ Both buffers must be the same length.\n  const expected = Buffer.from(expectedSignature, &#39;hex&#39;);\n  const received = Buffer.from(signatureHeader, &#39;hex&#39;);\n\n  if (expected.length !== received.length) {\n    return false;\n  }\n\n  return crypto.timingSafeEqual(expected, received);\n}\n\napp.post(&#39;\/webhooks\/tolinku&#39;, (req, res) =&gt; {\n  const signature = req.headers[&#39;x-webhook-signature&#39;];\n\n  if (!verifySignature(req.body, signature)) {\n    console.warn(&#39;Webhook signature verification failed&#39;);\n    return res.status(401).json({ error: &#39;Invalid signature&#39; });\n  }\n\n  \/\/ Signature is valid. Parse and process the event.\n  const event = JSON.parse(req.body.toString());\n  console.log(&#39;Verified event:&#39;, event.event);\n\n  \/\/ Process the event asynchronously to respond quickly.\n  processEvent(event).catch(console.error);\n\n  res.status(200).json({ received: true });\n});\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A few critical details in this code:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Use the raw request body.<\/strong> The signature is computed over the exact bytes sent by the platform. If you parse the JSON first and then re-serialize it, whitespace differences or key reordering will produce a different hash. Always compute the HMAC over the raw body buffer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Use <code>crypto.timingSafeEqual<\/code>.<\/strong> A naive string comparison (<code>===<\/code>) leaks timing information. An attacker can measure how long the comparison takes to determine how many bytes of the signature are correct, then brute-force the rest. The <a href=\"https:\/\/nodejs.org\/api\/crypto.html#cryptotimingsafeequala-b\" rel=\"nofollow noopener\" target=\"_blank\"><code>timingSafeEqual<\/code><\/a> function takes constant time regardless of where the mismatch occurs.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Return 401 for invalid signatures.<\/strong> Do not return 200 for failed verification. A 401 response tells the sender (and any monitoring systems) that the request was rejected for authentication reasons.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Preventing Replay Attacks with Timestamps<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">HMAC signing alone does not prevent replay attacks. If an attacker captures a valid signed request, the signature remains valid indefinitely because the payload has not changed. To mitigate this, include a timestamp in the signed payload and enforce a tolerance window on the receiving end.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Most webhook platforms include a timestamp header alongside the signature. The signature is computed over both the timestamp and the body, so an attacker cannot modify the timestamp without invalidating the signature.<\/p>\n\n\n\n<pre><code class=\"language-javascript\">const TIMESTAMP_TOLERANCE_MS = 5 * 60 * 1000; \/\/ 5 minutes\n\nfunction verifySignatureWithTimestamp(payload, signatureHeader, timestampHeader) {\n  if (!signatureHeader || !timestampHeader) {\n    return false;\n  }\n\n  \/\/ Check timestamp freshness.\n  const timestamp = parseInt(timestampHeader, 10);\n  const now = Date.now();\n\n  if (Math.abs(now - timestamp) &gt; TIMESTAMP_TOLERANCE_MS) {\n    console.warn(&#39;Webhook timestamp outside tolerance window&#39;);\n    return false;\n  }\n\n  \/\/ The signed content includes the timestamp to prevent\n  \/\/ an attacker from replacing the timestamp on a captured\n  \/\/ request.\n  const signedContent = `${timestampHeader}.${payload.toString()}`;\n\n  const expectedSignature = crypto\n    .createHmac(&#39;sha256&#39;, WEBHOOK_SECRET)\n    .update(signedContent)\n    .digest(&#39;hex&#39;);\n\n  const expected = Buffer.from(expectedSignature, &#39;hex&#39;);\n  const received = Buffer.from(signatureHeader, &#39;hex&#39;);\n\n  if (expected.length !== received.length) {\n    return false;\n  }\n\n  return crypto.timingSafeEqual(expected, received);\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A five-minute tolerance window is a reasonable default. It accounts for clock drift between servers and network latency while still blocking replays of old requests. The <a href=\"https:\/\/www.standardwebhooks.com\/\" rel=\"nofollow noopener\" target=\"_blank\">Standard Webhooks<\/a> specification recommends a similar approach, combining a timestamp with the signature to form a verifiable, time-bound token.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For additional replay protection, you can store processed event IDs and reject duplicates. This provides defense in depth: even if a replayed request somehow falls within the timestamp window, the duplicate ID check catches it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">IP Allowlisting<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Signature verification is your primary defense, but IP allowlisting adds a useful secondary layer. If your webhook platform publishes a list of IP addresses that send webhook traffic, you can configure your firewall or application to reject requests from any other source.<\/p>\n\n\n\n<pre><code class=\"language-javascript\">const ALLOWED_IPS = new Set([\n  \/\/ Replace with your platform&#39;s published webhook IPs.\n  &#39;203.0.113.10&#39;,\n  &#39;203.0.113.11&#39;,\n  &#39;198.51.100.5&#39;,\n]);\n\nfunction isAllowedIP(req) {\n  const clientIP = req.headers[&#39;x-forwarded-for&#39;]?.split(&#39;,&#39;)[0].trim()\n    || req.socket.remoteAddress;\n  return ALLOWED_IPS.has(clientIP);\n}\n\napp.post(&#39;\/webhooks\/tolinku&#39;, (req, res) =&gt; {\n  if (!isAllowedIP(req)) {\n    return res.status(403).json({ error: &#39;Forbidden&#39; });\n  }\n\n  \/\/ Continue with signature verification...\n});\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">IP allowlisting is not a substitute for signature verification. IP addresses can be spoofed at the network layer, and platforms may add new IPs without notice. Treat it as defense in depth, not a standalone mechanism.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">TLS and HTTPS Requirements<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Every webhook endpoint should be served over HTTPS. This is non-negotiable. Without TLS, the entire webhook payload (including the signature header) travels in plaintext across the network. A network-level attacker could read, modify, or replay any request.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Most webhook platforms, including <a href=\"https:\/\/tolinku.com\/docs\/user-guide\/webhooks\/signing-and-verification\/\">Tolinku<\/a>, require HTTPS endpoints and will refuse to deliver events to plain HTTP URLs. If you are developing locally, tools like <a href=\"https:\/\/ngrok.com\/\" rel=\"nofollow noopener\" target=\"_blank\">ngrok<\/a> or <a href=\"https:\/\/theboroer.github.io\/localtunnel-www\/\" rel=\"nofollow noopener\" target=\"_blank\">localtunnel<\/a> provide HTTPS tunnels for testing.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Beyond basic TLS, consider these additional transport-layer practices:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Enforce TLS 1.2 or higher.<\/strong> Older versions have known vulnerabilities.<\/li>\n<li><strong>Use a valid certificate from a trusted CA.<\/strong> Self-signed certificates may cause delivery failures.<\/li>\n<li><strong>Enable HSTS headers<\/strong> to prevent protocol downgrade attacks.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Secret Rotation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Webhook secrets should not live forever. Regular rotation limits the damage if a secret is leaked. The challenge is rotating without downtime: if you change the secret and the platform sends a webhook signed with the new secret before your server is updated, verification fails and the event is lost.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The solution is a dual-secret verification window:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Generate a new secret in the platform.<\/li>\n<li>Update your server to accept signatures from both the old and new secrets.<\/li>\n<li>Update the webhook configuration in the platform to use the new secret.<\/li>\n<li>After confirming deliveries succeed with the new secret, remove the old secret from your server.<\/li>\n<\/ol>\n\n\n\n<pre><code class=\"language-javascript\">const WEBHOOK_SECRETS = [\n  process.env.WEBHOOK_SECRET_CURRENT,\n  process.env.WEBHOOK_SECRET_PREVIOUS,\n].filter(Boolean);\n\nfunction verifySignatureMultiSecret(payload, signatureHeader) {\n  if (!signatureHeader) {\n    return false;\n  }\n\n  const received = Buffer.from(signatureHeader, &#39;hex&#39;);\n\n  for (const secret of WEBHOOK_SECRETS) {\n    const expectedSignature = crypto\n      .createHmac(&#39;sha256&#39;, secret)\n      .update(payload)\n      .digest(&#39;hex&#39;);\n\n    const expected = Buffer.from(expectedSignature, &#39;hex&#39;);\n\n    if (expected.length === received.length\n      &amp;&amp; crypto.timingSafeEqual(expected, received)) {\n      return true;\n    }\n  }\n\n  return false;\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A quarterly rotation schedule is a good starting point. If your organization handles sensitive data (financial transactions, health records), consider monthly rotation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Common Vulnerabilities to Avoid<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Even with signing in place, several implementation mistakes can undermine your webhook security:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Parsing JSON before verifying.<\/strong> If you use <code>express.json()<\/code> middleware on your webhook route, the raw body is discarded. You end up computing the HMAC over a re-serialized version of the payload, which will not match the original signature. Always use <code>express.raw()<\/code> for webhook routes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Logging secrets.<\/strong> Webhook secrets should never appear in logs, error messages, or stack traces. Treat them like database passwords. Store them in environment variables or a secrets manager, never in source code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Ignoring failed verifications.<\/strong> Some implementations log a warning for invalid signatures but still process the event. This defeats the entire purpose of signing. Failed verification must result in a rejected request, every time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Hardcoding the secret.<\/strong> If the secret is in your source code, it is in your version control history, your CI\/CD logs, and potentially your Docker images. Use environment variables or a service like <a href=\"https:\/\/docs.aws.amazon.com\/secretsmanager\/latest\/userguide\/intro.html\" rel=\"nofollow noopener\" target=\"_blank\">AWS Secrets Manager<\/a>, <a href=\"https:\/\/developer.hashicorp.com\/vault\/docs\" rel=\"nofollow noopener\" target=\"_blank\">HashiCorp Vault<\/a>, or your cloud provider&#39;s equivalent.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Skipping verification in development.<\/strong> It is tempting to bypass signature checks in local development. Do not. Use your platform&#39;s test mode or generate a local signing secret. Skipping verification in development builds habits that carry into production.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Testing Signature Verification<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before deploying your webhook receiver, verify that your implementation correctly rejects invalid signatures. Here is a test script that generates a signed payload and sends it to your local endpoint:<\/p>\n\n\n\n<pre><code class=\"language-javascript\">const crypto = require(&#39;crypto&#39;);\nconst http = require(&#39;http&#39;);\n\nconst secret = &#39;your-test-secret&#39;;\nconst body = JSON.stringify({\n  event: &#39;link.clicked&#39;,\n  timestamp: new Date().toISOString(),\n  data: { link_id: &#39;lnk_test123&#39;, url: &#39;https:\/\/example.com\/test&#39; }\n});\n\nconst signature = crypto\n  .createHmac(&#39;sha256&#39;, secret)\n  .update(body)\n  .digest(&#39;hex&#39;);\n\nconst options = {\n  hostname: &#39;localhost&#39;,\n  port: 3000,\n  path: &#39;\/webhooks\/tolinku&#39;,\n  method: &#39;POST&#39;,\n  headers: {\n    &#39;Content-Type&#39;: &#39;application\/json&#39;,\n    &#39;X-Webhook-Signature&#39;: signature,\n    &#39;X-Webhook-Event&#39;: &#39;link.clicked&#39;,\n    &#39;User-Agent&#39;: &#39;Tolinku\/1.0&#39;,\n  },\n};\n\nconst req = http.request(options, (res) =&gt; {\n  console.log(`Status: ${res.statusCode}`);\n});\n\nreq.write(body);\nreq.end();\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Run this script with the correct secret and confirm you get a 200 response. Then change the secret or modify the body after signing and confirm you get a 401. Both cases need to work correctly.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For more comprehensive testing, tools like <a href=\"https:\/\/webhook.site\/\" rel=\"nofollow noopener\" target=\"_blank\">Webhook.site<\/a> let you inspect payloads during development, and the <a href=\"https:\/\/www.standardwebhooks.com\/\" rel=\"nofollow noopener\" target=\"_blank\">Standard Webhooks<\/a> project provides reference implementations you can test against.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Putting It All Together<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A production-grade webhook receiver combines all of these protections into a layered defense:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>HTTPS only.<\/strong> Reject or redirect any plain HTTP requests.<\/li>\n<li><strong>IP allowlisting.<\/strong> Block requests from unknown sources at the network or application level.<\/li>\n<li><strong>Signature verification.<\/strong> Compute the HMAC and compare using a timing-safe function.<\/li>\n<li><strong>Timestamp validation.<\/strong> Reject requests outside a five-minute tolerance window.<\/li>\n<li><strong>Idempotency.<\/strong> Store processed event IDs and skip duplicates.<\/li>\n<li><strong>Secret rotation.<\/strong> Support multiple active secrets during rotation windows.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Each layer addresses a different attack vector. Together, they make your webhook integration resilient against spoofing, tampering, replay attacks, and unauthorized access.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Tolinku&#39;s <a href=\"https:\/\/tolinku.com\/docs\/user-guide\/webhooks\/signing-and-verification\/\">webhook signing documentation<\/a> covers the platform-specific details: which headers are used, how the signing content is structured, and where to find your webhook secret in the dashboard. If you are just getting started with webhooks, the companion article on <a href=\"https:\/\/tolinku.com\/blog\/webhooks-integrations-deep-linking\/\">webhooks and integrations for deep linking<\/a> covers the broader architecture, event types, and integration patterns.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Secure your webhooks with HMAC signing and verification. Prevent spoofed events, replay attacks, and unauthorized access to your deep link data.<\/p>\n","protected":false},"author":2,"featured_media":1115,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"Webhook Security: HMAC Signing and Verification Guide","rank_math_description":"Secure your webhooks with HMAC signing and verification. Prevent spoofed events, replay attacks, and unauthorized access to your deep link data.","rank_math_focus_keyword":"webhook security signing","rank_math_canonical_url":"","rank_math_facebook_title":"","rank_math_facebook_description":"","rank_math_facebook_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-webhook-security-signing.png","rank_math_facebook_image_id":"","rank_math_twitter_title":"","rank_math_twitter_description":"","rank_math_twitter_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-webhook-security-signing.png","footnotes":""},"categories":[15],"tags":[62,218,20,264,69,36,93,61],"class_list":["post-1116","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-engineering","tag-api","tag-authentication","tag-deep-linking","tag-engineering","tag-mobile-development","tag-privacy","tag-security","tag-webhooks"],"_links":{"self":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1116","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/comments?post=1116"}],"version-history":[{"count":2,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1116\/revisions"}],"predecessor-version":[{"id":2249,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1116\/revisions\/2249"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media\/1115"}],"wp:attachment":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media?parent=1116"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/categories?post=1116"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/tags?post=1116"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}