Void a credit note
What changed
You can now void an issued credit note. A single call moves the note to a terminal voided state and posts a reversing entry that undoes the original ledger and VAT-return effect in full. The original issue record and its journal are kept, so the correction is append-only rather than a deletion.
curl -X POST https://api.speybooks.com/v1/credit-notes/cn_5/void \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: 7c3f...redacted" \
-d '{ "reason": "Issued in error: duplicate of CN-0002" }'
{
"success": true,
"data": {
"creditNoteId": "cn_5",
"status": "voided",
"voidReason": "Issued in error: duplicate of CN-0002"
}
}
Why it matters
A credit note raised in error used to be a dead end: there was no clean way to take it back once issued. Now you can correct it and keep a complete trail. Nothing is erased, the original note and its entry stay on the record, and a matching reversing entry sits alongside them, so an auditor can see both the mistake and its correction.
The correction is dated today, not backdated to the original issue date. HMRC treats voiding an erroneously issued note as an error correction rather than a change in consideration, so it belongs in the current period, not the period of the original note. Error corrections are subject to HMRC’s normal four-year capping rules.
The reversal is rated, not return-neutral. It carries the VAT back out line by line, so your VAT return returns to the true position rather than leaving output tax overstated. That is the treatment HMRC’s guidance requires for an erroneously issued note: it is an error correction, and a void that left the VAT untouched would misstate the return. You get the correct figure without having to work it out by hand.
The route protects you from a half-done correction. A note that is still crediting an invoice cannot be voided until you reverse those allocations first, so you can never leave an invoice pointing at a note that no longer exists. Only an issued note can be voided, the reason is recorded, and a repeated call is safe to retry.
Proof and impact
The terminal state and the reversing entry are enforced at the database level (migration 113), not only in the service, so the guarantees hold regardless of how the write arrives. The requirement that live allocations be zero before a void is enforced the same way. The pairing of a void with its reversing entry is verified at every deploy.
Voiding requires a signed-in user; an API key cannot void a credit note. The call is idempotent under an Idempotency-Key, and a second void of the same note is rejected.
Breaking changes: none. This is a new endpoint; existing behaviour is unchanged.