Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Eseperio/verifactu-php/llms.txt

Use this file to discover all available pages before exploring further.

InvoiceCancellation (XML schema: RegistroAnulacionType) voids a previously registered invoice record in AEAT. It extends InvoiceRecord and shares most base fields with InvoiceSubmission.
use eseperio\verifactu\models\InvoiceCancellation;

$cancellation = new InvoiceCancellation();
Pass a populated instance to Verifactu::cancelInvoice().

Properties inherited from InvoiceRecord

These fields are identical in behaviour to their counterparts on InvoiceSubmission. Refer to the InvoiceSubmission reference for full descriptions.
PropertyTypeRequiredDescription
$versionIdstringYes (default '1.0')Schema version (IDVersion)
$invoiceIdInvoiceIdYesInvoice being cancelled (IDFacturaAnulada) — set via setInvoiceId()
$chainingChainingYesHash-chain link to previous record — set via setChaining() or setAsFirstRecord()
$systemInfoComputerSystemYesBilling software info — set via setSystemInfo()
$recordTimestampstringYesISO 8601 timestamp of record generation
$hashTypeHashTypeYes (default SHA_256)Always HashType::SHA_256
$hashstringAutoSHA-256 chain hash, computed automatically
$fechaFinVeriFactustring|nullNoEnd date for voluntary VERI*FACTU cessation (31-12-YYYY format)

Cancellation-specific properties

Required fields

issuerName
string
required
Full legal name of the invoice issuer (NombreRazonSocialEmisor). Must match the name used when the original invoice was registered. Example: 'Mi Empresa S.L.'

Optional fields

externalReference
string
External reference string (RefExterna, optional). Free-form identifier for your internal records. Note: this property is named externalReference on InvoiceCancellation (vs. externalRef on InvoiceSubmission).
noPreviousRecord
YesNoType
No-previous-record indicator (SinRegistroPrevio, optional). Set to YesNoType::YES when cancelling an invoice that was never successfully registered with AEAT (e.g. it was rejected at the time of submission and a prior registration record does not exist).
Enum caseValue
YesNoType::YES'S'
YesNoType::NO'N'
previousRejection
YesNoType
Previous rejection indicator (RechazoPrevio, optional). Set to YesNoType::YES to flag that the original submission attempt was rejected by AEAT and this cancellation covers that rejected record.
generator
GeneratorType
Who generated this cancellation record (GeneradoPor, optional). Used when the cancellation is not initiated by the tax obligor themselves.
Enum caseValueDescription
GeneratorType::ISSUER'E'The obliged issuer generated the cancellation
GeneratorType::RECIPIENT'D'The invoice recipient generated it
GeneratorType::THIRD_PARTY'T'A third party generated it
generatorData
LegalPerson
Identity of the generator (Generador, optional). Required when generator is set to RECIPIENT or THIRD_PARTY. Set via setGeneratorData(). See LegalPerson.

Methods

setInvoiceId(InvoiceId|array $invoiceId): static

Sets the identification of the invoice to be cancelled. The values must exactly match those used when the invoice was originally registered.
$cancellation->setInvoiceId([
    'issuerNif'    => 'B12345678',
    'seriesNumber' => 'A-2025/001',
    'issueDate'    => '2025-01-15',
]);

setChaining(Chaining|array $chaining): static

Sets the hash-chaining link. Cancellation records are part of the same submission chain as registration records, so this must reference the hash of the immediately preceding record (registration or cancellation).

setAsFirstRecord(): static

Marks this cancellation as the first record in a chain. Rarely needed for cancellations — use only if no prior records exist for this issuer/system combination.

setSystemInfo(ComputerSystem|array $systemInfo): static

Sets the billing system information. See ComputerSystem.

setGeneratorData(LegalPerson|array $generatorData): static

Sets the identity of the entity that generated the cancellation. Accepts a LegalPerson object or an array with name and either nif or otherId keys.
use eseperio\verifactu\models\LegalPerson;
use eseperio\verifactu\models\enums\GeneratorType;

$cancellation->generator = GeneratorType::RECIPIENT;

$recipient = new LegalPerson();
$recipient->name = 'Client Corp S.A.';
$recipient->nif  = 'A87654321';
$cancellation->setGeneratorData($recipient);

// Array shorthand
$cancellation->setGeneratorData([
    'name' => 'Client Corp S.A.',
    'nif'  => 'A87654321',
]);

toXml(): \DOMDocument

Deprecated. This method always throws an \Exception. Use InvoiceSerializer::toCancellationXml() instead. XML generation was moved to the InvoiceSerializer service and calling toXml() directly on a cancellation model will fail at runtime.

validate(): array

Validates all properties against the combined rule set (parent + cancellation-specific rules). Returns an empty array on success, or an associative error array on failure.

Complete example

<?php

use eseperio\verifactu\Verifactu;
use eseperio\verifactu\models\InvoiceCancellation;
use eseperio\verifactu\models\ComputerSystem;
use eseperio\verifactu\models\LegalPerson;
use eseperio\verifactu\models\PreviousInvoiceChaining;
use eseperio\verifactu\models\Chaining;
use eseperio\verifactu\models\enums\YesNoType;

$cancellation = new InvoiceCancellation();

// Required fields
$cancellation->issuerName      = 'Mi Empresa S.L.';
$cancellation->recordTimestamp = date('Y-m-d\TH:i:sP');

// Identify the invoice to cancel
$cancellation->setInvoiceId([
    'issuerNif'    => 'B12345678',
    'seriesNumber' => 'A-2025/001',
    'issueDate'    => '2025-01-15',
]);

// Chain to the previous record (the original registration)
$prev = new PreviousInvoiceChaining();
$prev->issuerNif    = 'B12345678';
$prev->seriesNumber = 'A-2025/001';
$prev->issueDate    = '15-01-2025';  // DD-MM-YYYY in PreviousInvoiceChaining
$prev->hash         = 'abc123def456...'; // hash from the previous submission

$chaining = new Chaining();
$chaining->setPreviousInvoice($prev);
$cancellation->setChaining($chaining);

// Billing software
$provider = new LegalPerson();
$provider->name = 'Verifactu PHP SDK';
$provider->nif  = 'B99999999';

$system = new ComputerSystem();
$system->providerName          = 'Verifactu PHP SDK';
$system->systemName            = 'MyERP';
$system->systemId              = '01';
$system->version               = '2.0.0';
$system->installationNumber    = '1';
$system->onlyVerifactu         = YesNoType::YES;
$system->multipleObligations       = YesNoType::NO;
$system->hasMultipleObligations    = YesNoType::NO;
$system->setProviderId($provider);
$cancellation->setSystemInfo($system);

// Optional: indicate no prior AEAT registration existed
// $cancellation->noPreviousRecord = YesNoType::YES;

$errors = $cancellation->validate();
if (!empty($errors)) {
    throw new \RuntimeException('Cancellation validation failed: ' . json_encode($errors));
}

$response = Verifactu::cancelInvoice($cancellation);

if ($response->submissionStatus === 'Correcto') {
    echo 'Invoice successfully cancelled.';
}

Build docs developers (and LLMs) love