One endpoint.
Every credential operation.
Upload files, stamp them on-chain, verify hashes, stream events, and generate signed links — all through a single REST path with header-based routing. No blockchain libraries. No IPFS nodes. Just HTTP.
All on /webhook/{apikey}
File to blockchain in one request
POST a file with stamp-immediately: true and Chainletter handles IPFS pinning, CIDv0 computation, on-chain stamping, and ledger indexing. One round-trip.
No file? Send a JSON body with a CID to register a hash. Or send nothing to create a group.
// Upload a file and stamp immediately const res = await fetch("https://service-link.clstamp.com/webhook/YOUR_API_KEY", { method: "POST", headers: { "secret-key": "YOUR_SECRET_KEY", "group-id": "my-credentials", "stamp-immediately": "true" }, body: formData // FormData with 'file' field }); // → 201 { "success": true, "hash": "QmNPHR...", "files_stamped": 1 }
Three workflows, one GET
No group-id? Returns all groups. Include it? Files with fresh stamping status. Add a hash header? Full verification — contract, tx ID, every IPCM stamp for that CID.
const res = await fetch("https://service-link.clstamp.com/webhook/YOUR_API_KEY", { headers: { "secret-key": "YOUR_SECRET_KEY", "hash": "QmU4AvzpnrJRfKDe9KBvTUxCLJ..." } }); // → 200 { "data": { "contract": "0x6019ab8cb194...8b2bdd", "created": 1748620068, "foreign_tx_id": "0x21c3e85c..." }, "allResults": [ /* every IPCM stamp */ ] }
Stamp an entire collection at once
Upload files into a group over time, then PATCH to stamp them all on-chain in one transaction. Efficient for diploma runs, compliance audits, bulk certifications.
const res = await fetch("https://service-link.clstamp.com/webhook/YOUR_API_KEY", { method: "PATCH", headers: { "secret-key": "YOUR_SECRET_KEY", "group-id": "spring-2025-diplomas" } }); // → 200 { "success": true, "files_stamped": 247, "network": "public" }
Server-Sent Events for every action
Open an SSE connection and receive events the moment they happen. Build reactive dashboards, audit logs, or integrations without polling.
const events = new EventSource( "https://service-link.clstamp.com/webhook/YOUR_API_KEY/events/stream", { headers: { "secret-key": "YOUR_SECRET_KEY" } } ); events.onmessage = (e) => { const event = JSON.parse(e.data); console.log(event.type, event.data); };
Client-side uploads without exposing keys
Generate time-limited signed upload URLs for your end users. No proxy needed, no keys exposed. Set expiration, size limits, and MIME types per link.
const res = await fetch( "https://service-link.clstamp.com/webhook/YOUR_API_KEY/upload-link" + "?expires=3600&max_file_size=5242880", { headers: { "secret-key": "YOUR_SECRET_KEY" } } ); // → 200 { "upload_url": "https://uploads.pinata.cloud/v3/...", "expires_in": 3600 }
Full endpoint reference
| Method | Path | Description |
|---|---|---|
| POST | /webhook/{apikey} | Upload file, register hash, or create group. Optional immediate stamping. |
| GET | /webhook/{apikey} | List groups, list files (with bulk check), or verify a hash. |
| PATCH | /webhook/{apikey} | Stamp all files in a group on-chain. |
| HEAD | /webhook/{apikey} | Status — credits, group stats via response headers. |
| DELETE | /webhook/{apikey} | Remove a file by hash. |
| GET | .../events/stream | SSE — real-time stream of all events. |
| GET | .../upload-link | Signed upload URL for client-side IPFS uploads. |
| GET | .../download-link | Signed download URL with optional image resizing. |
| GET | .../list-remote | List remote Pinata files by group. |
| POST | .../jwt | Single-use JWT (30-day validity). |
Authentication
Two values. Both in headers. That's it.
API Key
Path parameter. Identifies your tenant and routes to your IPCM contract.
secret-key
Request header. Authenticates you as the key owner. Use signed upload links for browser uploads.
const res = await fetch("https://service-link.clstamp.com/webhook/YOUR_API_KEY", { method: "HEAD", headers: { "secret-key": "YOUR_SECRET_KEY", "group-id": "my-credentials" } }); // Response headers: X-Credits: 847 X-Total-Files: 23 X-Total-Size: 48234567
Start stamping credentials today
Get your API key, make a POST, and your first credential is on-chain.
