Skip to main content
When you’ve matched a receipt from your collection to an OpenCard transaction, POST it here:
POST https://api.opencard.io/api/v1/service/marcet/callback/{referenceId}
{referenceId} = OpenCard transaction reference from the match request.

Required headers

HeaderValue
X-EventCallbackRequestResolved or CallbackRequestDeleted
X-CallbackRequest-IdCallback request ID from OpenCard
X-Data-SignatureHMAC-SHA256(raw_body, client_secret)

Signature calculation

import hmac, hashlib

signature = hmac.new(
    client_secret.encode(),
    request_body_bytes,
    hashlib.sha256
).hexdigest()
const crypto = require('crypto');
const sig = crypto.createHmac('sha256', clientSecret)
  .update(rawBody)
  .digest('hex');
Must match X-Data-Signature header exactly. Raw body bytes, not re-serialized JSON.

Resolved payload

Content type depends on callback type configured for the request:
  • application/xml — receipt XML (parsed for VAT + line items)
  • application/json — structured receipt data
OpenCard extracts:
  • True VAT rates and amounts → transaction.true.vat webhook
  • Line items → transaction.line.items webhook
  • Receipt file → stored, URL sent via receipt.fetched webhook

Response

CodeMeaning
200Accepted
403Bad signature
404Unknown callback request ID
Duplicate CallbackRequestResolved for already-resolved requests → 200 (idempotent, logged as warning).

What happens after

  1. Receipt file downloaded and stored in cloud
  2. TrueVAT records created
  3. LineItem records created
  4. Webhooks fired to EMS (per org webhook config)