fulkruma.delivery.created.v1
Fires when a delivery grant is issued for a digital-type product — either by a direct POST /api/v1/deliveries call or by the Plugipay-checkout webhook on completed checkout for a digital product. Subscribe to email the buyer their download link or kick off any post-purchase fulfilment automation.
When it fires
Inside the same Prisma transaction as the Delivery insert. Exactly one emission per (productId, checkoutSessionId) pair — the 409 DUPLICATE guard on the create endpoint ensures retries don't double-fire.
The grant is immediately valid: downloads: 0, expiresAt defaulting to 14 days out, ready to serve.
Payload
{
"id": "evt_01HXAB7K3M9N2P5QRS8TVWXY3Z",
"type": "fulkruma.delivery.created.v1",
"occurredAt": "2026-05-12T10:42:00.123Z",
"accountId": "acc_01HX...",
"data": {
"deliveryId": "del_01HXAB7K3M9N2P5QRS8TVWXY3Z",
"productId": "prod_01HX...",
"customerId": "cus_01HX...",
"checkoutSessionId": "cs_01HX..."
}
}
The payload is the minimal join keys. Fetch the full delivery (including maxDownloads, expiresAt) via GET /api/v1/deliveries/:id.
Handler examples
// Node
if (event.type === 'fulkruma.delivery.created.v1') {
const { deliveryId, productId, customerId, checkoutSessionId } = event.data;
const product = await catalog.get(productId);
await mailer.send(customerId, {
template: 'digital_delivery',
productName: product.name,
downloadUrl: `https://your-app.com/d/${deliveryId}`,
});
}
# Python
if event["type"] == "fulkruma.delivery.created.v1":
d = event["data"]
product = catalog.get(d["productId"])
mailer.send(d["customerId"], template="digital_delivery",
product_name=product.name, download_url=f"https://your-app.com/d/{d['deliveryId']}")
// Go
if event.Type == "fulkruma.delivery.created.v1" {
var d struct{ DeliveryID, ProductID, CustomerID, CheckoutSessionID string }
_ = json.Unmarshal(event.Data, &d)
mailer.SendDigitalDelivery(ctx, d.CustomerID, d.ProductID, d.DeliveryID)
}
What to do
- Email the buyer the download link (Fulkruma doesn't send transactional email itself in v1).
- Provision any per-customer access (cloud bucket pre-signed URL, watermarking, etc.).
- Increment analytics counters for digital sales.
Common pitfalls
- Linking directly to the asset. Build a wrapper endpoint on your side that looks up the delivery, records the download with
POST /api/v1/deliveries/:id/download(which enforces expiry and the download count), and then signs the asset URL. Don't put a permanent storage URL in the email. - Issuing the email twice on retry. Dedupe on
event.id. At-least-once delivery means duplicates are expected on transient failures. - Forgetting
expiresAt. The default 14-day cutoff isn't surfaced in this payload — fetch the full delivery if you want to put an expiry date in the email.
Related events
fulkruma.delivery.downloaded.v1— a download recorded withPOST /api/v1/deliveries/:id/download.fulkruma.delivery.expired.v1— its download window closed.fulkruma.delivery.updated.v1— extended, reset or revoked.
Next
- Webhooks reference.
- Deliveries resource.
- Licenses resource — for license-key fulfilment.