Skip to main content

Tax Credit Voucher — CCF (03)

The CCF (type 03) is issued between VAT contributors. The recipient must have an NRC assigned by MH. Unlike Invoice (01), the CCF explicitly breaks down the 13% VAT on the document and allows the recipient to deduct it on their tax return.

CCF stands for "Comprobante de Crédito Fiscal", the Spanish term used in the signed DTE and MH documents.

When to use CCF

When the recipient:

  • Has an NRC assigned (registered as VAT contributor).
  • Requires tax credit for their accounting.
  • Is a legal entity or a natural person with formal economic activity.

If the recipient has no NRC, issue Invoice (01) instead.

Technical details

MethodPOST
URLhttps://ocote.io/api/connect/invoice (same endpoint, doc_type: "03")
Content-Typeapplication/json
AuthenticationHeader Authorization: Bearer odt_...

Request

Structurally identical to Invoice (01) with three critical differences:

  1. doc_type must be "03".
  2. customer is required and has specific mandatory fields.
  3. customer.type_contributor determines whether automatic VAT withholding applies.

Customer fields required in CCF

FieldRequiredDescription
nameYesContributor's business name.
nitYesRecipient's NIT.
nrcYesRecipient's NRC.
type_contributorYes1=Small, 2=Medium, 3=Large, 4=Government.

The remaining fields (activity_code, department, municipality, email, etc.) are optional but recommended — see the full table in Invoice (01) > Customer.

Automatic withholding for Large Taxpayers and Government

When type_contributor is 3 (Large) or 4 (Government) and amount_taxable >= 100.00, the API automatically applies a 1% VAT withholding on the taxable base. You don't send any extra field or do any calculations. See Wildcard items > 1% VAT withholding.

Response

Structurally identical to Invoice 01. In CCF the amount fields are especially relevant:

FieldCalculation
amount_taxableTaxable base = sum of (quantity × unit_price × (1 − discount)) after removing the 13% VAT.
amount_vat13% VAT = amount_taxable × 0.13.
amount_grossVAT-included total = amount_taxable + amount_vat.
amount_retentionamount_taxable × 0.01 if type_contributor4 and amount_taxable >= 100; else 0.
amount_totalNet total = amount_gross − amount_retention.

Example: CCF to Large Taxpayer

curl
curl -X POST https://ocote.io/api/connect/invoice \
-H "Authorization: Bearer odt_xxx" \
-H "Content-Type: application/json" \
-d '{
"doc_type": "03",
"external_ref": "CCF-2026-0042",
"customer": {
"name": "LARGE COMPANY, S.A. DE C.V.",
"nit": "06140710141035",
"nrc": "2360090",
"type_contributor": 3,
"activity_code": "86902",
"department": "06",
"municipality": "14",
"address": "Boulevard Los Héroes, San Salvador",
"email": "accounting@largecompany.com"
},
"lines": [
{
"description": "Custom software development - April 2026",
"quantity": 1,
"unit_price": 5000.00
}
],
"payment_method": "05",
"transaction_condition": 2,
"deadline": 30
}'
Node.js (axios)
const { data } = await axios.post(
'https://ocote.io/api/connect/invoice',
{
doc_type: '03',
external_ref: 'CCF-2026-0042',
customer: {
name: 'LARGE COMPANY, S.A. DE C.V.',
nit: '06140710141035',
nrc: '2360090',
type_contributor: 3,
activity_code: '86902',
department: '06',
municipality: '14',
address: 'Boulevard Los Héroes, San Salvador',
email: 'accounting@largecompany.com',
},
lines: [
{ description: 'Custom software development - April 2026',
quantity: 1, unit_price: 5000.00 },
],
payment_method: '05',
transaction_condition: 2,
deadline: 30,
},
{ headers: { Authorization: `Bearer ${process.env.OCOTE_API_KEY}` } }
);
Python (requests)
r = requests.post(
"https://ocote.io/api/connect/invoice",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"doc_type": "03",
"external_ref": "CCF-2026-0042",
"customer": {
"name": "LARGE COMPANY, S.A. DE C.V.",
"nit": "06140710141035",
"nrc": "2360090",
"type_contributor": 3,
"activity_code": "86902",
"department": "06",
"municipality": "14",
"address": "Boulevard Los Héroes, San Salvador",
"email": "accounting@largecompany.com",
},
"lines": [
{
"description": "Custom software development - April 2026",
"quantity": 1,
"unit_price": 5000.00,
},
],
"payment_method": "05",
"transaction_condition": 2,
"deadline": 30,
},
)
PHP (Guzzle)
$response = $client->post('invoice', [
'headers' => ['Authorization' => 'Bearer ' . getenv('OCOTE_API_KEY')],
'json' => [
'doc_type' => '03',
'external_ref' => 'CCF-2026-0042',
'customer' => [
'name' => 'LARGE COMPANY, S.A. DE C.V.',
'nit' => '06140710141035',
'nrc' => '2360090',
'type_contributor' => 3,
'activity_code' => '86902',
'department' => '06',
'municipality' => '14',
'address' => 'Boulevard Los Héroes, San Salvador',
'email' => 'accounting@largecompany.com',
],
'lines' => [
[
'description' => 'Custom software development - April 2026',
'quantity' => 1,
'unit_price' => 5000.00,
],
],
'payment_method' => '05',
'transaction_condition' => 2,
'deadline' => 30,
],
]);

Successful response with withholding

{
"success": true,
"dte_success": true,
"contingency": false,
"rejected": false,
"posted": true,
"is_duplicate": false,

"document_id": "a1b2c3d4-1234-5678-9abc-def012345678",
"external_ref": "CCF-2026-0042",
"control_number": "DTE-03-M001P001-000000000000042",
"generation_code": "A1B2C3D4-1234-5678-9ABC-DEF012345678",
"reception_stamp": "20260421154532...",

"amount_taxable": 4424.78,
"amount_vat": 575.22,
"amount_gross": 5000.00,
"amount_retention": 44.25,
"amount_total": 4955.75,

"ticket_url": "",
"json_url": "https://ocote.io/api/connect/file/a1b2c3d4-1234-5678-9abc-def012345678?type=json&key=odt_xxx"
}

Notice:

  • You sent unit_price: 5000.00 VAT-included. The API extracted the VAT: taxable base 4424.78, VAT 575.22, sum 5000.00.
  • Because the recipient is type_contributor: 3 (Large Taxpayer) and the base exceeds $100, VAT withholding was applied: 4424.78 × 0.01 = 44.25.
  • The net total the recipient must pay is 5000.00 − 44.25 = 4955.75.
  • ticket_url is empty — CCFs don't generate a thermal ticket; use json_url or the PDF available from the Ocote platform.

CCF-specific validation errors

In addition to general /invoice errors, CCF validates:

MessageCause
Crédito Fiscal requiere datos del clientecustomer not sent.
NIT es requerido para Crédito Fiscalcustomer.nit empty.
NRC es requerido para Crédito Fiscalcustomer.nrc empty.
Nombre del cliente es requerido para Crédito Fiscalcustomer.name empty.
Tipo de contribuyente es requerido para Crédito Fiscalcustomer.type_contributor not sent.

Query and modify afterwards

  • Query status: GET /status/CCF-2026-0042
  • Invalidate: POST /invalidate/CCF-2026-0042. If the CCF is outside the direct-invalidation window, the API automatically issues a Credit Note (05) that adjusts it — see Credit Note.
  • Issue NC against this CCF: POST /credit-memo with document_id pointing to the CCF — see Credit Note.

See also