Invoice API - 'id' und 'objectName' Required

Bein Erstellen einer neuen Rechnung erhalte ich am Endpoint „Invoice/Factory/saveInvoice“ folgende Fehlermeldung: „invoice expected array with ‚id‘ and ‚objectName‘. array given

In der API Doku (finally ok :slight_smile: !) finde ich kein direktes invoice-id oder invoice-objectName Property.
Id und objectName sehe ich nur für „contact“ und „contactPerson“.

Siehe:
https://my.sevdesk.de/api/InvoiceAPI/doc.html#operation/createInvoiceByFactory

Vielen Dank!

*P.S: für zukünftige Developer: *
Hier gibt’s ein cooles PHP Beispiel bzgl. create Invoice, send Mail, etc.
Auf die API muss halt acht gegeben werden :slight_smile: SevDesk Create Invoice ($4) · Snippets · Snippets · GitLab

Nachtrag:
Mit invoice[objectName] = Invoice scheint es zu funktionieren.
Das sehe ich in der API Doku aber nicht - Bitte entsprechend nachtragen!
Dafür erhalte ich jetzt einen anderen Fehler:
Integrity constraint violation: 1048 Column ‚invoice_date‘ cannot be null, query was: INSERT INTO invoice (invoice_number, contact, create, update, sev_client, invoice_date, header,…
Merkwürdig, da im Request definitiv ein invoiceDate gesetzt ist.

Hallo, der im PS erwähnte Link erklärt nur wie man Invoices mit mehreren Requests erzeugt.

Die Doku gibt die Factories als bevorzugt an (“This endpoint is /Invoice/Factory/saveInvoice and we would always recommend to create invoices over it.” – https://5677.extern.sevdesk.dev/apiOverview/index.html#/doc-invoices#creation)

Mehrere Requests geben auch immer eine gute Gelegenheit dass manche tun und man dann verwaiste Objekte “herumhängen” hat.

Ich bekomme aber bei dem /saveInvoice Endpoint die gleiche Fehler wie oben wenn ich invoice[objectName] auf "Invoice" setzen und invoice[id] weglasse oder auf den String „null“ (mal so probiert!) setze:

Status = 400

{
  "objects":null,
  "error":{
    "message":"invoice expected array with \'id\' and \'objectName\'. array given",
    "code":null,
    "data":null
  }
}

Wenn ich auf wohl probiert hin "" (leerer String) oder -1 übertrage, bekomme ich Status 500 mit der Meldung:

{"objects":null,"error":{"message":"No Model_Invoice with the id 0  was found","code":null,"data":null}}

(bei Leer-String - bei -1 ist hier entsprechend im Fehler auch -1 vorhanden).

Jedenfalls scheint er hier aber auf das Vorhandensein von invoice[id] einzugehen, hat man aber natürlich keine gültige beim neu erzeugen.

In der in der Doku erwähnten Postman Collection bei https://www.getpostman.com/collections/9a3a6320199dd156fbca ist invoice[id] beim “Create Invoice with saveInvoice” Request jedenfalls auch nicht vorhanden.

Gibt es doch irgendeine Art, mit dem …/saveInvoice Endpunkt zu arbeiten oder muss man wirklich einfach mit mehreren Requests & den damit verbundenen Nachteilen vorgehen?

Servus Bernd,

invoice[id] kannst du weglassen.
So sieht meine Erstellung aus:

‚invoice[contact][id]‘ => $customerID,
‚invoice[contact][objectName]‘ => ‚Contact‘,
‚invoice[invoiceDate]‘ => $invoiceDate_formated,
‚invoice[discount]‘ => 0,
‚invoice[deliveryDate]‘ => $invoiceDate_formated,
‚invoice[status]‘ => ‚1000‘,
‚invoice[smallSettlement]‘ => „true“,
‚invoice[contactPerson][id]‘ => ‚12345‘,
‚invoice[contactPerson][objectName]‘ => „SevUser“,
‚invoice[taxRate]‘ => ‚0‘,
‚invoice[taxText]‘ => „0“,
‚invoice[taxType]‘ => „custom“,
‚invoice[taxSet][id]‘ => „12345“,
‚invoice[taxSet][objectName]‘ => „TaxSet“,
‚invoice[invoiceType]‘ => „RE“,
‚invoice[currency]‘ => „EUR“,
‚invoice[mapAll]‘ => „true“,
‚invoice[objectName]‘ => ‚Invoice‘,
‚invoice[headText]‘ => $invoice_header,
‚invoice[footText]‘ => $invoice_footer,
‚invoice[header]‘ => 'Rechnung Nr. ’ . $nextInvoiceNumber,
‚invoice[sendDate]‘ => $invoiceDate_formated,
‚invoice[payDate]‘ => $invoiceDate_formated,

  'invoicePosSave[0][unity][id]' => '1',
  'invoicePosSave[0][unity][objectName]' => 'Unity',
  'invoicePosSave[0][taxRate]' => '0',
  'invoicePosSave[0][mapAll]' => 'true',
  'invoicePosSave[0][objectName]' => 'InvoicePos',
  'invoicePosSave[0][quantity]' => '1',
  'invoicePosSave[0][price]' => $part_price,
  'invoicePosSave[0][name]' => $part_name,
  'invoicePosSave[0][text]' => $part_text,

  'invoicePosDelete' => 'null',
  'discountSave' => 'null',
  'discountDelete' => 'null',
  'takeDefaultAddress' => 'true',

Gleiche das mit deinem Request ab. Melde dich sonst nochmal, wenn du etwas brauchst bei mir.

LG, Daniel

Danke, Problem war glaube ich einfach dass ich in einer Unterposition mapAll unterlassen hatte.

Jetzt habe ich allerdings das gleiche Problem wie Du hattest: Beschwerde über NULL im Datum, mit der ganzen Query im Fehler.

Was für Format hast Du verwendet? Ich habe probiert: Unix Timestamp (hat bei Orders bei anderer Gelegenheit getan, ISO-8601 und ISO-8601 mit ’ ’ statt dem ‚T‘, aber nix davon hat getan.

// Cretate New Invoice
$invoiceDate = new DateTime();
$invoiceDate_formated = $invoiceDate->format(‚d.m.Y‘);

Hmmm, danke, bekomme auch mit dem Format:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'invoice_date' cannot be null, query was: INSERT INTO `invoice` (`invoice_number`, `contact`, `create`, `update`, `sev_client`, `invoice_date`, `header`, `head_text`, `foot_text`, `time_to_pay`, `discount_time`, `discount`, `address_name`, `address_street`, `address_zip`, `address_city`, `address_country`, `pay_date`, `create_user`, `delivery_date`, `status`, `small_settlement`, `contact_person`, `tax_rate`, `tax_text`, `dunning_level`, `address_parent_name`, `address_contact_ref`, `tax_type`, `payment_method`, `cost_centre`, `send_date`, `origin`, `type_origin`, `origin_last_invoice`, `invoice_type`, `account_intervall`, `account_last_invoice`, `account_next_invoice`, `reminder_total`, `reminder_debit`, `reminder_deadline`, `reminder_charge`, `address_parent_name2`, `address_name2`, `tax_set`, `address_gender`, `account_start_date`, `account_end_date`, `address`, `currency`, `sum_net`, `sum_tax`, `sum_gross`, `sum_discounts`, `sum_net_foreign_currency`, `sum_tax_foreign_currency`, `sum_gross_foreign_currency`, `sum_discounts_foreign_currency`, `sum_net_accounting`, `sum_tax_accounting`, `sum_gross_accounting`, `paid_amount`, `entry_type`, `customer_internal_note`, `show_net`, `enshrined`, `send_type`, `delivery_date_until`, `datev_connect_online`, `send_payment_received_notification_date`, `account_datev`, `sum_discount_net`, `sum_discount_gross`, `sum_discount_net_foreign_currency`, `sum_discount_gross_foreign_currency`, `tax_rule`) VALUES (?, ?, UNIX_TIMESTAMP(NOW()), UNIX_TIMESTAMP(NOW()), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

Frag mich was das wirklich weggemacht hat bei Dir.

Die Fehlermeldungen sind ja oft nicht wirklich verwandt mit ihrer Ursache. invoice[invoiceDate] war ja sowieso nie NULL, aber anscheinend ist es auch nicht das Problem, dass es ein falsches Format als NULL ankommen hat lassen…

BTW auch mal probiert, testhalber obwohl bei mir irrelevant sein sollte folgende Felder zu setzen wie Du sie hattest:

  'invoicePosDelete' => 'null',
  'discountSave' => 'null',
  'discountDelete' => 'null',

Damit bekomme ich auch 500,

{"objects":null,"error":{"message":"Call to a member function getId() on null","code":null,"data":null}}

Komisch wie das zu variieren scheint.

Hast du die meine gesetzten Properties angesehen? Ich weiß nicht mehr genau, was dann bei mir zum Erfolg führte - Aber die aktuell gesetzten Properties funktionieren.

AFAIK sind die Felder required oder?

Ja, folgendes Zitat würde drauf hindeuten, aber mit ihnen bekomme ich eben eine noch weirdere Fehlermeldung wie oben.

Naja, werde wohl einfach den Einen Offiziellen Request™ von Postman abschreiben und dann einzelne Felder ändern um zu sehen wo es kaputt geht. Einzigartiges Erlebnis, diese API.

Hm ja, scheint so… So habe ich es dann auch gemacht.
Ja, sehe ich genauso, da gibt es noch einige Kinderkrankheiten…

OK, habe das Problem gefunden:

Hatte für mapAll ‚false‘ gesetzt, weil ich nie was überschreiben sondern nur erzeugen wollte & einen Fehler wenn schon ein Objekt existiert.

Anscheinend ist hier nur ‚true‘ erlaubt und das Feld ist eine Konstante die nur existiert um eine Gelegenheit für Fehler zu geben? :joy: Hoffentlich gibt’s nie eine versehentliche Datenwiederholung oder der Request rödelt halt drüber! ¯\(ツ)

Glückwunsch :smiley: Ich finde, es sollten Preise vergeben werden, wenn Entwickler es schaffen, die API korrekt verwenden zu können und die Fehler finden :wink:
All the best!

LG

5 „Gefällt mir“

haha danke gleichfalls :smiley:

Hi zusammen,

ich habe den gleichen Fehler wie ganz oben beschrieben und setze Python 3 ein: {„objects“:null,„error“:{„message“:„invoice expected array with ‚id‘ and ‚objectName‘. array given“,„code“:null,„data“:null}}

Ich setze folgende API ein: https://my.sevdesk.de/api/v1/Invoice/Factory/saveInvoice

Ich bin mir eigentlich sehr sicher, dass alle Parameter vorhanden sind, da ich diese zunächst ein mal mit POSTMAN getestet habe.
Mein Vermutung ist hier folgendes: Ich habe mir den urlencoded payload string aus POSTMAN:
invoice%5BinvoiceNumber%5D=RE-%3C%3CINVOICE-NR%3E%3E&invoice%5Bcontact%5D%5Bid%5D=25315330&invoice%5Bcontact%5D%5BobjectName%5D=Contact&invoice%5BinvoiceDate%5D=1613628899&invoice%5Bheader%5D=Rechnung%20Nr.%20%3C%3CINVOICE-NR%3E%3E&invoice%5Bstatus%5D=100&invoice%5BinvoiceType%5D=RE&invoice%5Bcurrency%5D=EUR&invoice%5BmapAll%5D=true&invoice%5BobjectName%5D=Invoice&invoice%5Bdiscount%5D=false&invoice%5BcontactPerson%5D%5Bid%5D=362659&invoice%5BcontactPerson%5D%5BobjectName%5D=SevUser&invoice%5BtaxType%5D=default&invoice%5BtaxRate%5D=0&invoice%5BtaxText%5D=0&invoicePosSave%5B0%5D%5Bpart%5D%5Bid%5D=7263118&invoicePosSave%5B0%5D%5Bpart%5D%5BobjectName%5D=Part&invoicePosSave%5B0%5D%5Bprice%5D=7%2C99&invoicePosSave%5B0%5D%5Bquantity%5D=2000&invoicePosSave%5B0%5D%5BtaxRate%5D=0&invoicePosSave%5B0%5D%5Bunity%5D%5Bid%5D=1&invoicePosSave%5B0%5D%5Bname%5D=Anzahl%20Nutzer%3A%20Nutzungs%C3%BCberlassung%20Plattform%0A(Dienstleistung)%20lms.digital-medical.academy&invoicePosSave%5B0%5D%5Bunity%5D%5BobjectName%5D=Unity&invoicePosSave%5B0%5D%5BobjectName%5D=InvoicePos&invoicePosSave%5B0%5D%5BmapAll%5D=true&invoicePosDelete=null&discountSave=null&discountDelete=null&takeDefaultAddress=true&invoice%5BdeliveryDate%5D=2021-02-01T06%3A44%3A43%2B01%3A00&invoice%5BdeliveryDateUntil%5D=2021-02-28T06%3A44%3A43%2B01%3A00&invoice%5BheadText%5D=Sehr%20geehrte%20Damen%20und%20Herren%2C%3C%2Fbr%3Evielen%20Dank%20f%C3%BCr%20Ihren%20Auftrag%20und%20das%20damit%20verbundene%20Vertrauen!%3C%2Fbr%3EHiermit%20stelle%20ich%20Ihnen%20die%20folgenden%20Leistungen%20in%20Rechnung%3A&invoice%5BfootText%5D=Bitte%20%C3%BCberweisen%20Sie%20den%20Rechnungsbetrag%20unter%20Angabe%20der%20Rechnungsnummer%20auf%20das%20unten%20angegebene%20Konto.%3C%2Fbr%3EDer%20Rechnungsbetrag%20ist%20sofort%20f%C3%A4llig.%3C%2Fbr%3EMit%20freundlichen%20Gr%C3%BC%C3%9Fen%3C%2Fbr%3E%5B%25KONTAKTPERSON%25%5D&invoice%5BaddressCountry%5D%5Bid%5D=1&invoice%5BaddressCountry%5D%5BobjectName%5D=StaticCountry

genommen hier: https://www.urlencoder.org/ decoded um dann in meinem python script im anschluss nowendige parameter anzupassen.

Danach url-encode ich den String wieder mit urllib.parse.quote(invoice_payload).

Kann es sein, dass bei der en & decoden irgendwas verloren geht?

Grüße

Leon

Schwer zu sagen ohne lang die Details zu prüfen, aber was für mich am Schluss (verwende eigentlich auch Py3) gut funktioniert hat war, die Requests library zu verwenden und die Daten in einem dict aufzubauen, was ziemlich flexibel war:

invoice_data = {
  'invoice[invoiceNumber]': 'ourInvoiceNumberScheme'
  ...
}

requests.post(f"{self.url}/Invoice/Factory/saveInvoice", timeout=self.timeout,
                                 headers={'Authorization': self.api_key, 'Accept': 'application/json'},
                                 data=invoice_data)

Das war so viel weniger fitzelig als von Hand String zu bauen.

1 „Gefällt mir“

Hi Bernd,

ich probiers aus und gib dir bescheid ob das tut :wink:

EDIT:
Es hat wieder den selben Fehler geworfen, dann habe ich aber folgenden Header entfernt: 'Content-Type': 'application/x-www-form-urlencoded'und nun tut es.

Vielen Dank für die Hilfe :slight_smile:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'invoice_date' cannot be null, query was: INSERT INTO `invoice` (`invoice_number`, `contact`, `create`, `update`, 

API returns this error when mapAll - used bool value. Should be string. YES, bool as string:

mapAll: "true"

all bolean params should be string =)