links
POST /v1/site-links/ingest
Receive one batch of a site's outbound-link scan (signed webhook).
ਪ੍ਰਮਾਣੀਕਰਨ
ਇਹ ਐਂਡਪੁਆਇੰਟ ਜਨਤਕ ਹੈ। ਇਹ ਕੋਈ ਕ੍ਰੈਡਿਸ਼ੀਅਲ ਅਤੇ ਕੋਈ ਸੰਸਥਾ ਨਹੀਂ ਲੈਂਦਾ — ਇਹ ਉਹੀ ਹੈ ਜਿਸਨੂੰ ਸਾਡੀ ਆਪਣੀ ਮਾਰਕੀਟਿੰਗ ਸਾਈਟ ਅਤੇ AI ਜਵਾਬ ਇੰਜਣ ਪੜ੍ਹਦੇ ਹਨ।
ਇਹ ਐਂਡਪੁਆਇੰਟ ਕੋਈ ਸੰਸਥਾ ਆਈਡੀ ਨਹੀਂ ਲੈਂਦਾ। ਤੁਹਾਡੀ ਕੁੰਜੀ ਪਹਿਲਾਂ ਹੀ ਉਸ ਸੰਸਥਾ ਦੀ ਪਛਾਣ ਕਰਦੀ ਹੈ ਜਿਸ ਨਾਲ ਇਹ ਸਬੰਧਤ ਹੈ, ਅਤੇ ਜਵਾਬ ਉਸੇ ਤੱਕ ਸੀਮਤ ਹੈ।
ਕੋਸ਼ਿਸ਼ ਕਰੋ
ਕੋਈ ਵੀ ਚੀਜ਼ ਜੋ ਕੋਣ ਵਾਲੇ ਬਰੈਕਟਾਂ ਵਿੱਚ ਹੈ ਉਸਨੂੰ ਆਪਣੇ ਖੁਦ ਦੇ ਮੁੱਲਾਂ ਨਾਲ ਬਦਲੋ, ਅਤੇ ਕੁੰਜੀ ਪਲੇਸਹੋਲਡਰ ਨੂੰ ਆਪਣੇ ਡੈਸ਼ਬੋਰਡ ਦੀ ਇੱਕ ਕੁੰਜੀ ਨਾਲ ਬਦਲੋ।
curl -X POST https://api.zinndigital.com/v1/site-links/ingest \
-H "Content-Type: application/json" \
-d '{ "site": <string>, "scan_id": <string> }'ਲੌਗ ਇਨ ਕੀਤਾ ਹੋਇਆ ਹੈ? ਤੁਹਾਡੇ ਡੈਸ਼ਬੋਰਡ ਵਿੱਚ API ਕੰਸੋਲ ਤੁਹਾਡੀ ਅਸਲ ਸੰਸਥਾ ਆਈਡੀ (organisation id) ਅਤੇ ਤੁਹਾਡੀ ਆਪਣੀ ਕੁੰਜੀ ਨੂੰ ਭਰਦਾ ਹੈ, ਅਤੇ ਲਾਈਵ API ਦੇ ਵਿਰੁੱਧ ਬੇਨਤੀ ਚਲਾਉਂਦਾ ਹੈ ਤਾਂ ਜੋ ਤੁਸੀਂ ਅਸਲ ਜਵਾਬ ਦੇਖ ਸਕੋ। API ਕੰਸੋਲ ਵਿੱਚ ਇਸ ਐਂਡਪੁਆਇੰਟ ਨੂੰ ਖੋਲ੍ਹੋ
ਵੇਰਵੇ
What a site's Zinn® plugin POSTs when its scheduled link scan runs: the posts it looked at, and for each one every outbound `<a>` tag it found, with how many times that tag appears in that post. **Machine-to-machine; there is no principal.** Authentication is the **same HMAC scheme** `ingestSiteEvents` uses — SHA-256 over `"<timestamp>\n<body>"` in `X-Zinn-Cache-Signature`, with `X-Zinn-Cache-Timestamp` carrying the unix seconds, against a secret **derived** per site from the platform master key. ⛔ Deliberately not a second scheme: one secret, one derivation, one place for the two ends to agree. The organisation comes from the **resolved site** and never from the body. **A scan is a SNAPSHOT, delivered in batches.** One pass over a site carries one `scan_id` across as many requests as it takes; the request carrying `complete: true` triggers reconciliation, which deletes every post and placement for that site not stamped with that pass. ⛔ That is what makes a link the customer **removed** disappear from the report — an append-only index rots into a permanent overcount and looks authoritative while it does. ⛔ **An abandoned pass deletes nothing.** No completing batch, no sweep: the report goes stale rather than wrong-by-deletion. ⛔ **A batch from a superseded pass is ignored whole** and answers `ignored: true`. The plugin's POST is fire-and-forget with a two-second timeout, so a batch landing after the next cron tick has begun is expected; mixing it in would let a finished pass sweep away the live one's rows. **Every refusal is uninformative on purpose** — an unknown hostname is a bare `404` and a bad signature a bare `401`, because a chattier answer would tell anyone who can guess a hostname which domains this platform hosts.
ਪੈਰਾਮੀਟਰ
| ਨਾਮ | ਕਿਸਮ | ਲਾਜ਼ਮੀ | ਕੀ ਹੈ ਇਹ |
|---|---|---|---|
X-Zinn-Cache-Timestamp (header) | string | ਹਾਂ | Unix seconds. Signed as part of the material, which is what bounds a replay. |
X-Zinn-Cache-Signature (header) | string | ਹਾਂ | `sha256=<hex>`. |
ਬੇਨਤੀ ਬਾਡੀ
| ਨਾਮ | ਕਿਸਮ | ਲਾਜ਼ਮੀ | ਕੀ ਹੈ ਇਹ |
|---|---|---|---|
site | string | ਹਾਂ | The site's own `home_url()`. **An untrusted claim** — it selects which site's derived secret the signature is checked against, and nothing more. |
scan_id | string | ਹਾਂ | Identifies the **pass**, not the request. Minted by the plugin, because one pass spans many requests and the engine cannot mint it. Opaque: nothing is inferred from its value, a… |
complete | boolean | ਨਹੀਂ | ⛔ Only a literal `true` ends the pass. A missing key, a `null` or the string `"false"` all mean "not complete", because reading one as complete would sweep away every post the s… |
posts_sent | integer | ਨਹੀਂ | Posts this **pass** has sent so far, cumulative across batches, as counted by the site. ⛔⛔ Load-bearing on the completing batch: the POST is non-blocking, so a site never learns… |
posts | object[] | ਨਹੀਂ | — |
ਜਵਾਬ
| ਨਾਮ | ਕਿਸਮ | ਲਾਜ਼ਮੀ | ਕੀ ਹੈ ਇਹ |
|---|---|---|---|
accepted | boolean | ਹਾਂ | — |
ignored | boolean | ਹਾਂ | The batch belonged to a **superseded** pass and was dropped whole. Expected occasionally: the plugin's POST is fire-and-forget with a two-second timeout. |
posts | integer | ਹਾਂ | — |
links | integer | ਹਾਂ | — |
truncated | boolean | ਹਾਂ | A post reported more links than the per-post ceiling and the tail was dropped. Surfaced rather than swallowed — a report that silently under-counts is worse than one that says i… |
reconciled | boolean | ਹਾਂ | This batch completed the pass, so the snapshot sweep ran. |
removed | integer | ਹਾਂ | Rows the sweep deleted. ⭐ The only externally visible proof the snapshot reconciliation works: a site whose links change while this stays `0` on every pass is the append-only ro… |
refused | string | ਨਹੀਂ | Why a **completing** batch was not swept, when it was not — a lost batch, or one whose post list was truncated. ⛔ Reported rather than swallowed: a pass that keeps completing wi… |
ਇਹ ਐਂਡਪੁਆਇੰਟ ਜੋ ਗਲਤੀਆਂ ਵਾਪਸ ਕਰ ਸਕਦਾ ਹੈ
401 · 404 · 422 · 503