API mocks
DIAN-compatible electronic invoicing (Colombia)
A mock of DIAN's electronic invoicing web service (WcfDianCustomerServices), with the semantics of the habilitación test environment. It covers:
- sending UBL 2.1 invoices, credit notes and debit notes;
- the test set;
- status queries;
- the numbering range.
Every document is validated on the rules DIAN's verdicts hinge on, and answered with DIAN's DianResponse and a signed ApplicationResponse. It is provider-neutral: it stands in for DIAN itself, so your own software or any technology provider's can send to it.
Test environment only: documents must carry ProfileExecutionID 2, and nothing is reported to DIAN. Testlie is not affiliated with DIAN. "DIAN" is used only to describe API compatibility.
Connect
Create a DIAN-compatible e-invoicing system under ERP, then point your client at it:
- Endpoint: use
<base URL>/WcfDianCustomerServices.svcin place ofhttps://vpfe-hab.dian.gov.co/WcfDianCustomerServices.svc. - WSDL:
<base URL>/WcfDianCustomerServices.svc?wsdl. - Protocol: SOAP 1.2 (
Content-Type: application/soap+xml), with the operation as the body's element in thehttp://wcf.dian.colombianamespace.
| Credential | Environment variable | Use |
|---|---|---|
| Issuer NIT | DIAN_NIT |
AccountingSupplierParty CompanyID; GetNumberingRange accountCode |
| Software id | DIAN_SOFTWARE_ID |
sts:SoftwareID; GetNumberingRange softwareCode |
| Software PIN | DIAN_SOFTWARE_PIN |
SoftwareSecurityCode, and the CUDE of notes |
| Test set id | DIAN_TEST_SET_ID |
SendTestSetAsync testSetId |
| Technical key | DIAN_TECHNICAL_KEY |
The CUFE of invoices; the sample endpoint's bearer token |
| Numbering authorization, prefix | DIAN_INVOICE_AUTHORIZATION, DIAN_INVOICE_PREFIX |
sts:InvoiceControl; invoices are numbered SETP990000000 to SETP995000000 |
| ApplicationResponse certificate | DIAN_MOCK_SIGNING_CERT |
Verifies the mock's signed ApplicationResponse |
WS-Security: every request needs a wsse:Security header with an unexpired wsu:Timestamp and an X.509 BinarySecurityToken. Any test certificate works, and no certificate authority is checked. If the header has a ds:Signature, it must verify with that certificate and sign wsa:To, the wsu:Timestamp or the soap:Body (any of them, as WS-Security policies differ); a signature over none of them is refused. Otherwise the answer is the WCF fault "An error occurred when verifying security for the message.", and the call doesn't count against your plan.
Operations
| Operation | Parameters | Answer |
|---|---|---|
SendBillSync |
fileName, contentFile (a base64 ZIP with one XML) |
DianResponse |
SendBillAsync |
fileName, contentFile (up to 50 XMLs) |
UploadDocumentResponse with a ZipKey |
SendTestSetAsync |
fileName, contentFile, testSetId |
UploadDocumentResponse; an unknown test set is reported in ErrorMessageList |
GetStatus |
trackId: the CUFE or CUDE |
DianResponse |
GetStatusZip |
trackId: the ZipKey |
One DianResponse per document |
GetNumberingRange |
accountCode, accountCodeT, softwareCode |
OperationCode 100 with the range, resolution and technical key; 301 when the NIT or software is not the mock's |
A DianResponse has these fields:
IsValid;StatusCodeandStatusDescription:00processed correctly;99errors in mandatory fields;98still being validated;66unknown track id;
StatusMessage, e.g. "La Factura electrónica SETP990000001, ha sido autorizada.";ErrorMessage, a list ofRegla: <code>, Rechazo: <message>orRegla: <code>, Notificación: <message>;XmlDocumentKey(the CUFE or CUDE) andXmlFileName;XmlBase64Bytes: a UBLApplicationResponsethat references the document. ItsResponseCodeis02when the document is validated and04when it is rejected, with oneLineResponseper rule. Its sender is DIAN (NIT800197268, check digit 4), as in DIAN's own answers. It is signed XAdES-EPES (enveloped, RSA-SHA256, DIAN's política de firma v2, rolethird party) with the mock's test certificate, not DIAN's.
Asynchronous sends are validated straight away. GetStatusZip, and GetStatus for their documents, answer 98 until the mock's async delay has passed. With the Outcome scenario "requires action" they stay in process.
What is validated
| Rule | Rejection |
|---|---|
ZB01 |
The XML is not a well-formed UBL 2.1 Invoice, CreditNote or DebitNote, or ID, UUID, IssueDate or IssueTime is missing |
FAD02 / CAD02 / DAD02 |
ProfileExecutionID is not 2: production documents are refused |
FAJ21 … |
The issuer NIT is not the mock's |
FAB19, FAB27 … |
sts:SoftwareID is not the mock's, or SoftwareSecurityCode is not SHA-384(SoftwareID + PIN + document number) |
FAB07, FAB05 |
(Invoices) wrong numbering authorization, or a prefix or number outside the range |
FAD06 / CAD06 / DAD06 |
The CUFE or CUDE in UUID is not computed correctly |
FAU04, FAU14 … |
LineExtensionAmount is not the sum of the lines; PayableAmount is not TaxInclusiveAmount − allowances + charges − prepaid |
FAS07 … |
The tax subtotals don't add up to their TaxTotal |
ZE02 |
The document's enveloped signature is missing or does not verify with its own X509Certificate. For a XAdES-EPES signature, also when its SignedProperties aren't signed or SigningCertificate doesn't name that certificate. The certificate chain is not checked. |
90 |
A document with this CUFE or CUDE was validated before; the first validation stands |
Notifications, which don't reject:
CBG03/DBG03: a note'sBillingReferencethat this mock hasn't validated;TL-ZE01: the signature is plain XML-DSig, without XAdES-EPES qualifying properties. DIAN requires XAdES-EPES under its política de firma v2, so expect a real rejection;TL-ZE02: a XAdES signature withoutSigningTime;TL-ZE03: a XAdES signature whoseSigPolicyIdis nothttps://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf.
The first letter of a code follows the document type: F invoice, C credit note, D debit note. ZB01, ZE02, FAD06 and 90 are DIAN's own codes. Every other code is the mock's: those following DIAN's naming, and the TL- ones, which have no DIAN counterpart. Their messages end with "[regla del mock de Testlie; no es un código oficial de la DIAN]". Check them against the Anexo Técnico before your code depends on an exact code.
CUFE (invoices) and CUDE (notes) are computed as in the Anexo Técnico: SHA-384 of ID + IssueDate + IssueTime + LineExtensionAmount + 01 + IVA + 04 + INC + 03 + ICA + PayableAmount + issuer NIT + customer CompanyID + key + ProfileExecutionID. Amounts have two decimals, and taxes come from the document-level TaxTotal by TaxScheme/ID. The key is the technical key for the CUFE and the software PIN for the CUDE.
The Outcome scenario "decline" rejects every otherwise valid document with the chosen rule (FAD06, ZE02, FAB05, FAJ21 or FAB27).
Sample documents
POST <base URL>/__testlie/sample-document with Authorization: Bearer <technical key> and { "kind": "Invoice" | "CreditNote" | "DebitNote", "number"?, "referencedCufe"?, "lineAmount"? } returns:
xml: a complete UBL 2.1 document for this mock's software, signed XAdES-EPES as DIAN requires, with the right CUFE or CUDE, security code, range and totals;contentFile: the same document as a base64 ZIP;cufe;soapEnvelope: a readySendBillSyncrequest with a signed WS-Security header.
Use them to try the service, or as a reference for your own documents:
curl -s -X POST <base URL>/__testlie/sample-document -H "Authorization: Bearer $DIAN_TECHNICAL_KEY" \
-H 'Content-Type: application/json' -d '{"kind":"Invoice"}' > sample.json
jq -r .soapEnvelope sample.json | curl -s -X POST <base URL>/WcfDianCustomerServices.svc \
-H 'Content-Type: application/soap+xml; charset=utf-8' --data-binary @-Not implemented:
GetXmlByDocumentKey;SendEventUpdateStatusand the RADIAN events;- payroll (nómina) and support documents;
- the DIAN catalogue of every rule;
- certificate authority checks.