Carrying trade information in the sky
EasyUBL is the programmer's choice of REST-APIs for easy integration to the Peppol (Pan-European Public Procurement OnLine) network.Send Peppol documents through EasyUBL providing only the absolute minimum necessary information. EasyUBL takes care of the rest.
Receive Peppol documents through EasyUBL and enjoy the AI accounting proposals delivered with a json document version in addition to the raw XML document and a human-readable versions (PDF or HTML).
To work with EasyUBL API you have to be a tenant. As a tenant, you can set up companies that can send and receive documents. A tenant could, for example, be the developer of an ERP system, or a company that develops a component for an ERP system. The companies that use the ERP system, or the component, are the companies that the tenant creates. The endpoint is linked to the companies' registration numbers, VAT numbers, GLN numbers, etc. |
EasyUBL is an extension to Semantic.biz that transports documents. EasyUBL makes the documents usable for ERP systems.
|
You can immediately receive invoices by using the Accountant's page Once you have created a Tenant and obtained an API key, you can create your first company directly in the API's swagger page. To open the bookkeeper's page, you need a temporary key. This can be retrieved in the API's swagger page. The company you created can pin this link to the process bar in their browser. In the long term, the idea is that the application is accessed directly from the ERP system, but you can easily work with it from the process line. If you contact EasyUBL, we will immediately bring you to this point. |
At this stage, the companies receives UBL invoices/orders. The created companies have access to the documents they receive and must be started with accounting for cost creditors and the approval flow. If no one else sends you UBL invoices, EasyUBL will send you some. You can reject these in the approval flow, or delete them in the ERP system if you transfer them to the draft. |
API/Company/AddUpdateCompany |
HttpClient myClient = new HttpClient();
myClient.DefaultRequestHeaders.Add("Authorization", ApiKey); string myUrl = String.Concat("https://EasyUBL.net/api/Company/Update/", CompanyId); string myCompanyJson = JsonConvert.SerializeObject(myCompany); var stringContent = new StringContent(myCompanyJson, UnicodeEncoding.UTF8, "application/json"); var response = await myClient.PostAsync(myUrl, stringContent); response.EnsureSuccessStatusCode(); if (response.IsSuccessStatusCode) { var responseContent = await response.Content.ReadAsStringAsync(); string sub = (string)JsonConvert.DeserializeObject(responseContent); CompanyId = Guid.Parse(sub); // save the company guid in your application } |
- |
public class companyEasyUBL { public string name { get; set; } public string cvr { get; set; } public string currency { get; set; } public string country { get; set; } public string? webhookUrl { get; set; } public addEndpoint defaultEndpoint { get; set; } public addAddress defaultAddress { get; set; } public addContact defaultContact { get; set; } public addPayment payment { get; set; } public bool? DoNotReceiveUBL { get; set; } = false; } public class addEndpoint { public string endpointType { get; set; } public string endpointIdentifier { get; set; } } public class addAddress { public string? name { get; set; } public string? streetName { get; set; } public string? additionalStreetName { get; set; } public string? buildingNumber { get; set; } public string? inhouseMail { get; set; } public string? department { get; set; } public string? attensionName { get; set; } public string? cityName { get; set; } public string? postalCode { get; set; } public string? countrySubentity { get; set; } public string? countryCode { get; set; } } public class addContact { public string roleCode { get; set; } public string name { get; set; } public string email { get; set; } public string sms { get; set; } } public class addPayment { public string bankname { get; set; } public string bankRegNo { get; set; } public string bankAccount { get; set; } public string bic { get; set; } public string iban { get; set; } public string CreditorIdentifier { get; set; } } |
Feel free to use the source text for this application. If you turn to EasyUBL support, we will be happy to help with advice and guidance. |
Invoices are sent with the feature /api/ SendDocuments/ Invoice/ {companyId} The function demands "companyId" as a parameter to identify the sender company address (the supplier). This ensures that no one sends invoices on your behalf through EasyUBL. This information is found in your database after calling AddUpdate (create companies). The function SendDocuments/Invoice" sends the invoice and returns the complete UBL document. |
HttpClient myClient = new HttpClient(); myClient.DefaultRequestHeaders.Add("Authorization",myTenantKey); string myUrl = String.Concat("https:// EasyUBL.net/api /SendDocuments/ Invoice/", companyId); string myInvoiceJson = JsonConvert.SerializeObject(myInvoice); var stringContent = new StringContent(myInvoiceJson, UnicodeEncoding.UTF8, "application/json"); var response = await myClient.PostAsync(myUrl, stringContent); response.EnsureSuccessStatusCode(); myXmlDocument = await response.Content.ReadAsStringAsync(); |
You should archive the complete UBL document in the database. This is the legal document the recipient receives. In the event of disputes, the complete UBL document is what must be referred to. Human readable versions formed on the fly like PDF, HTML etc. must be
considered "copies with special features" like being human readable, but they are not the legal document. That is solely the actual complete UBL document. Some recipients have special requirements for the content, that must be agreed with the invoice issuing company. For example, this could be a requisition number, specific contact persons, accounting codes, cost centers etc. If the recipient has an elaborate system, a message will be returned, if any of these informations are missing. If the recipient behaves correctly, this message will indicate, where in the UBL document this information must be placed. This means that you will be notified very quickly after sending a document, and you can then add any missing information, if that's the case, and resend it right away, not having to hunt down someone at the sender, who knows where the information should be found in the document. Furthermore, the UBL document is the legal document. In the event of disputes, this is what must be referred to. Human readable versions can be considered copies with special abilities that are formed on the fly. |
The document may be built in this way. This is only an example to illustrate the scope. Data is read from an SQL server and placed in the json document. |
SqlDataReader myr = Comm.ExecuteReader(); if (myr.Read()) { int AddressID = (int)myr["So_addressID"]; if (AddressID == 0) errCode = 1; int CreInvFactor = (int)myr["CreInvFactor"]; if (CreInvFactor == -1) myI.invoiceCreditnote = "Cre"; else myI.invoiceCreditnote = "Inv"; myI.id = new(myr["InvoiceNo"].ToString()); myI.documentCurrencyCode = myr["Currency"].ToString().ToUpper(); myI.issueDate = (myr["InvDate"].Equals(DBNull.Value) ? DateTime.Today : (DateTime)myr["InvDate"]); myI.dueDate = (myr["PayDate"].Equals(DBNull.Value) ? DateTime.Today : (DateTime)myr["PayDate"]); myI.accountingCost = myr["AccountingCost"].ToString(); myI.buyerReference = myr["requisition"].ToString(); long OrderNo; long.TryParse(myr["OrderNo"].ToString(), out OrderNo); myI.salesOrderID = OrderNo.ToString(); myI.note = string.Concat(myr["text_1"], " ", myr["text_2"]).Trim(); if (myr["ShipDate"].Equals(DBNull.Value)) myI.deliveryDate = myI.issueDate; else myI.deliveryDate = (DateTime)myr["ShipDate"]; int thisContId = myr["ContID"] == DBNull.Value ? 0 : (int)myr["ContID"]; myI.accountingCustomerParty = GetPartyInfo((int)myr["So_addressID"]); myI.accountingCustomerParty.Contact = GetContactInfo((int)myr["So_addressID"], thisContId); if (string.IsNullOrEmpty(myI.accountingCustomerParty.Contact.name)) { myI.accountingCustomerParty.Contact.name = myI.accountingCustomerParty.name; } myI.totalAmount = (decimal)myr["amount"]; myI.accountingCustomerParty.postalAddress = GetPostalAddress((int)myr["Sh_addressID"]); if ((int)myr["Sh_addressID"] != 0) myI.deliverAddress = GetPostalAddress((int)myr["Sh_addressID"]); myI.invoiceLines = GetLines(saleID); } return myI; |
It is a traditional mapping of the fields found in the local database for the JSON document describing the invoice. Enjoy the fact that it is significantly easier to map for this document than to the underlying XML document.
Feel free to use the source text for this application. If you turn to Easyubl support, we will be happy to help with advice and guidance. |
To receive a webhook, you must have an api that can service all of your tenant's companies.
A webhook calls a url, that you provide when creating your tenant It could be: https://myBasicURL/api/ tools/ UBLNotifications The webhook call to your service will contain a small json document: { "companyId": "c9b89d84-cdb6-4207-8a99-23c7ffb04577", "endpointId": "df4967d4-7e4d-4f23-9653-b8bd1b8719b2", "ublDocumentId": "22323456", "documentStatusCode" : "5110", "documentType": "110", "actionCode": "2", "errorCode": "-1", "base64EncodedMessage": "Not sent", "externalIdentifier": "5053387" "documentXmlBase64Content" } CompanyId will make it possible to find the company in your application. This is the key that was returned, when you created the company. You probably don't use EndpointId for anything. ublDocumentID is an internal ID in the system, that makes it possible to backtrace the document. You don't use it. externalIdentifier will contain your invoice number/order number etc. depending on the document type. When you receive documents, the document is associated with the notification. You can therefore save the document in the ERP system as soon as it is received. The person(s) who must approve the document simultaneously receives the document for approval. The received document can be processed into usable data with the tools "Human readable", "Creditor Booking" and "Goods Handling" When you receive invoices from cost creditors, the received document is the accounting vaucher. You must therefore archive it as it is. This is the document the sender is responsible for. If the recipient system is not able to present a UBL document itself, you can archive the readable format in the recipient database. You can also simply save the UBL document and use EasyUBL to convert the document when it is displayed. Upon receipt, EasyUBL will send a copy of the document to an approver. This is not the "invoice" but a copy for the approver. It should not be saved. If the receiving system does not receive UBL documents at all, the recipient's copy can be perceived as the original. This is just as acceptable as only sending the invoice as a pdf document by email. Not all ERP systems are able to receive a webhook. We have the option of delivering notifications in other ways. The solution will depend on the receiving system. Contact easyUBL and we will find a solution. The ERP system must use vouchers for the accounts, goods transactions, orders and human-readable documents. Functions in Tools make these translations. The functions receive the archived document and return the data that is useful for the ERP system. |
Feel free to use the source text for this application. If you turn to EasyUBL support, we will be happy to help with advice and guidance. |
Who receives the invoice when it arrives You will receive creditor invoices associated with weehook notifications. You may archive them in the database immediately, or you may use them in your local approval flow. Alternatively, you can use "The bookkeeper's page" to interpret the invoices, handle invoice approval and translate invoices into postings that can be handled by the bookkeeper. The invoice document is attached to the posting as an xml and html document. A UBL invoice is sent electronically directly to the bookkeeper. This gives the accountant a new task of distributing invoices internally within the company. To avoid this, EasyUBL sends invoices directly to the person(s) who must approve the invoice. If no approvers have been created, EasyUBL will send the invoice to the invoice's contact person and, if this is missing, directly to the sender's company email. Approval/rejection of the invoice is sent directly back to the sender through the peppol network. This function is almost indispensable for smaller companies that have an external accountant who does not work for the company every day. The accountant's page can be called from the ERP system via a link. To open the page with the current company, a key is used that is extracted with the "TemporaryKey" function. This key is issued with a limited lifetime and a new key is issued each time the page is opened. If the lifetime is more than 5 seconds, a two-factor login is required. |