Using callback URLs

Proof callback URLs

To ensure the durability of the proofs you create on the Woleet platform, it is strongly recommended to download and keep your proof receipts safe as soon as they become available. To that purpose, the platform can inform you about the progress of the anchoring process by calling back URLs of your choice.

The callback URL must be specified at anchor creation time using the callbackURL property.

The Woleet platform performs a POST request on this URL whenever the status of the anchor changes. The anchor is provided as a JSON object in the request body.

The status of the anchor will take the following values (in sequence):

  • NEW: proof waiting to be sent to the blockchain (the proof receipt is not yet available for download)
  • SENT: proof sent to the blockchain (the proof receipt is available for download, but not yet for verification)
  • CONFIRMED: proof confirmed at least 6 times by the blockchain (the proof receipt is available for download and verification)

To sum up, the status of an anchor provided to a callback can be NEW, SENT or CONFIRMED.
You can download the associated proof receipt by using the Get receipt endpoint as soon as the status is SENT, and you can verify it by using the Verify receipt endpoint as soon as the status is CONFIRMED.

Signature request callback URLs

The platform can inform you about the progress of a signature request by calling back URLs of your choice.

The callback URL must be specified at signature request creation time using the callbackURL property.

The Woleet platform performs a POST request on this URL whenever:

  • its state property changes
  • a new signature is registered
  • its proofBundleComplete property is set to true (ie. proof bundle and the Signature Attestation document are ready to download)

The signature request is provided as a JSON object in the request body.

Retry policy

If the POST request on the callback URL fails for any reason (status code other than 2xx, host not reachable, TLS certificate invalid or untrusted) the Woleet platform will retry the call later.

The retry policy is the following:

  • the time between retries increases progressively (it is equal to the number of retries power 2 minutes, like 1mn, 4mn, 9mn, 16mn etc.)
  • callback will be definitively canceled after 14 days
  • the amount of retries within 14 days is approximately 40

Also keep in mind that if a new callback must be performed (because the state of an anchor or a signature request has changed) while a previous callback cannot not be notified, only the latest callback will be notified.

Verifying callback authenticity

To ensure that your callback URLs are called by Woleet, you can ask Woleet to sign the body of the callbacks using a HMAC-SHA1 function and a dedicated secret.

To enable this feature, you must go on Woleet ProofDesk (Developer -> Callback) and generate an API callback secret.

A signature will then be generated for each call and passed to your service in the x-woleet-signature header of the HTTP request as a Base64 value.

To verify it, you simply need to sign the body received using the same algorithm and compare the signatures.

Here is some sample code (JavaScript and Java) you can use to verify this signature:

const crypto = require('crypto')

// Sign the request body with your callback secret
const yourCallbackSecret = '...'
const yourSignature = crypto.createHmac('sha1', yourCallbackSecret).update(body).digest('base64')

// Checks that signatures match
const woleetSignature = ... // get the 'x-woleet-signature' header
if (yourSignature !== woleetSignature) {
    // Signautre is NOT valid...
}
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

...
  
// Sign the request body with your callback secret
String yourCallbackSecret = "...";
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(new SecretKeySpec(yourCallbackSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA1"));
String yourSignature = Base64.getEncoder().encodeToString(mac.doFinal(body.getBytes(StandardCharsets.UTF_8)));

// Checks that signatures match
String woleetSignature = request.getHeader("x-woleet-signature");
if (!yourSignature.equals(woleetSignature)) {
    // Signautre is NOT valid...
}