procuris

CRM und ERP

Neue passende Ausschreibungen automatisch als Verkaufschance im CRM, Fristen und Werte im ERP, mit Feldzuordnung und Schutz vor Dubletten.

Auf Anfrage

Diese Leistung erhalten Sie über ein individuelles Angebot.

Ihr CRM bekommt neue passende Ausschreibungen als Verkaufschance. Das CRM ist die Software, in der Ihr Vertrieb Kunden und Verkaufschancen führt. Die Verkaufschance trägt Frist, Auftraggeber und Auftragswert, soweit procuris sie kennt. Hat die Vergabestelle keinen Auftragswert veröffentlicht, kann ein geschätzter Wert kommen, der als geschätzt gekennzeichnet ist. Verschiebt die Vergabestelle die Frist, zieht das CRM nach. Ihr ERP, die Software für Aufträge, Planung und Buchhaltung, bekommt dieselben Daten für Angebotsplanung und Auswertung.

Die Anbindung baut Ihre IT oder Ihr Dienstleister. procuris liefert die Daten über Webhooks und, je nach Variante, zusätzlich über die API. Soll procuris die Anbindung bauen, nehmen wir das in Ihr Angebot auf.

Die Rezepte setzen nur eine Schnittstelle in Ihrem System voraus. Ihr CRM oder ERP muss Daten über eine eigene Schnittstelle annehmen. Salesforce, HubSpot, Microsoft Dynamics, Pipedrive und SAP bieten eine solche Schnittstelle. Einen fertigen Connector für ein bestimmtes Produkt gibt es nicht. Welches Feld wohin gehört, legen Sie selbst fest, nach der Tabelle unter Felder zuordnen.

Für ein CRM empfehlen wir einen eigenen kleinen Dienst. Ein Workflow-Builder käme ohne Programmierung aus, reicht aber nur für einfache Abläufe wie eine Teams-Nachricht. Der Abgleich mit dem CRM braucht in beiden Varianten eine Warteschlange und den Vergleich von Ständen. Variante A braucht zusätzlich eine Erstbefüllung über die API.

Rezept 1: Neuer Treffer wird Verkaufschance

Das Rezept hat zwei Varianten. Sie unterscheiden sich darin, welche Ausschreibungen ins CRM sollen und welche Zugänge Sie brauchen.

  • Variante A bringt alle Ausschreibungen zu Ihren Filtern für Branche und Region ins CRM (tender.published). Sie braucht API und Webhooks: die API für die Erstbefüllung und den nächtlichen Abgleich, Webhooks für alles dazwischen.
  • Variante B bringt nur die Treffer Ihrer Suchaufträge (search.hit). Sie braucht nur Webhooks. Eine Erstbefüllung entfällt.

Die Schritte 4, 5 und 9 gelten nur für Variante A.

Felder anlegen. Im CRM an der Verkaufschance ein eindeutiges Textfeld „procuris-ID“ für tender.id, ein Feld „procuris-Stand“ für lastModified, ein Zahlenfeld „Passung“ und ein Feld „Passung vom“ für den Zeitpunkt der Passung. Am Account oder Geschäftspartner ein eindeutiges Textfeld „procuris-Organisation“ für organizations[].id. Über „procuris-ID“ erkennt Ihr System dieselbe Ausschreibung wieder. Über „procuris-Organisation“ erkennt es denselben Auftraggeber, sofern procuris ihn als dieselbe Stelle erkannt hat. Zwei verschiedene id schließen nicht aus, dass es dieselbe Stelle ist. Dann entstehen im CRM zwei Accounts, die Ihr Vertrieb von Hand zusammenführt. Die Felder „procuris-Stand“ und „Passung vom“ braucht Schritt 7.

Empfänger mit Warteschlange bauen. Ein kleiner Dienst nimmt die Nachrichten an und prüft die Signatur mit einer fertigen Bibliothek aus Zustellung und Sicherheit. Danach legt er die Nachricht in eine Warteschlange und antwortet mit 2xx, bevor er ins CRM schreibt. So bleibt er unter den 15 Sekunden, die procuris auf eine Antwort wartet. Ins CRM schreibt er erst in Schritt 6.

Zieladresse anlegen und Ereignisse wählen. Die Person mit der Rolle Inhaber legt in procuris unter Einstellungen › Organisation › Webhooks die Adresse des Dienstes als Zieladresse an. Den Bereich Webhooks gibt es erst, wenn der Zugang nach Vertragsschluss eingerichtet ist. Bis dahin führt die gleichnamige Zeile im Abschnitt Auf Anfrage nur zur Anfrage eines Angebots. Variante A: die Ereignisarten tender.published mit den Filtern für Ihre Branche und Region, dazu tender.updated für geänderte Werte, Lose und Fristen und tender.archived zum Abschließen. Variante B: die Ereignisarten search.hit, tender.updated und tender.archived, dazu die Suchaufträge, deren Treffer ins CRM sollen. Legen Sie bei der Zieladresse fest, dass die Auswahl der Suchaufträge auch für tender.updated und tender.archived gilt. Dann kommen geänderte Werte, verschobene Fristen und Archivierungen zu jeder Ausschreibung, die schon einmal Treffer eines dieser Suchaufträge war, siehe Ereignisse. Ab dem Speichern laufen die gewählten Ereignisse in die Warteschlange. Ob sie dort ankommen, prüfen Sie mit Testnachricht senden.

Erstbefüllung (Variante A). Die Erstbefüllung bringt einmal alle Ausschreibungen ins CRM, die es zu Ihren Filtern schon gibt. Ihr Dienst merkt sich den Zeitpunkt, zu dem er beginnt. Dann ruft er über die API mit denselben Filtern ab, die bei der Zieladresse stehen, und legt je Ausschreibung eine Verkaufschance an, siehe Filter und Takt. Zu jeder Verkaufschance speichert er lastModified in „procuris-Stand“.

Nachholabruf (Variante A). Danach ruft er ein zweites Mal ab, mit updated_since gleich dem gemerkten Zeitpunkt aus Schritt 4. So bekommt er, was sich während der Erstbefüllung geändert hat.

Warteschlange abarbeiten. Erst jetzt verarbeitet der Dienst die Nachrichten aus der Warteschlange, danach jede neue. In Variante B kommen die ersten Treffer am Morgen nach dem Anlegen der Zieladresse. Die Reihenfolge der Nachrichten ist nicht garantiert, weil Wiederholungen und Nachlieferungen später ankommen können. Darum kann jedes Ereignis außer der Testnachricht eine Verkaufschance anlegen. Nachrichten mit data.test gleich true übergeht der Dienst.

Die procuris-ID entscheidet über Anlegen oder Nachziehen. Der Dienst sucht zuerst eine Verkaufschance mit procuris-ID gleich data.tender.id. Gibt es eine, gilt Schritt 7. Gibt es keine, legt er sie aus data.tender an, bei tender.archived gleich mit dem Status aus der Tabelle unter Status abbilden. Beim Anlegen speichert er data.tender.lastModified in „procuris-Stand“. Bei search.hit speichert er data.fit in „Passung“ und den timestamp der Nachricht in „Passung vom“. Den Auftraggeber sucht er über „procuris-Organisation“ und legt ihn nur an, wenn es ihn im CRM nicht gibt.

In Variante B kann eine Chance ohne Passung entstehen. Das passiert, wenn tender.updated oder tender.archived zu einem früheren Treffer kommt, zu dem das CRM noch keine Chance hat, etwa zu einem Treffer von vor dem Anlegen der Zieladresse. Nur search.hit trägt eine Passung. Das Feld „Passung“ bleibt dann leer.

Änderungen nachziehen. Ist data.tender.lastModified neuer als „procuris-Stand“, schreibt der Dienst alle zugeordneten Felder aus data.tender neu, nicht nur die aus changedFields. Danach speichert er das neue lastModified in „procuris-Stand“. Ist es älter oder gleich, übernimmt er aus data.tender nichts. data.fit übernimmt er nur, wenn der timestamp der Nachricht neuer ist als „Passung vom“, und speichert diesen timestamp dann dort. So überschreibt weder ein verspäteter noch ein nachgelieferter search.hit einen neueren Stand. Nachrichten zu Änderungen, die schon aus Erstbefüllung oder Nachholabruf im CRM stehen, fallen so weg. Zwischen Erstbefüllung und Webhooks entsteht in Variante A keine Lücke, weil die Warteschlange ab dem Speichern der Zieladresse läuft und die Erstbefüllung erst danach beginnt.

Abschließen. Bei tender.archived bildet der Dienst data.tender.archiveReason auf den Status im CRM ab, siehe Tabelle unter Status abbilden.

Nächtlicher Abgleich (Variante A). Der nächtliche Abgleich zieht herausgefallene Ausschreibungen nach und legt fehlende Chancen an. Passt eine Ausschreibung nach einer Änderung nicht mehr zu Ihren Filtern, etwa weil die Vergabestelle die Region korrigiert, kommt für sie kein tender.updated mehr, nur noch tender.archived. Darum ruft der Dienst jede Nacht über die API ohne inhaltliche Filter ab, nur mit updated_since.

Der erste nächtliche Lauf holt alles ab dem Start der Erstbefüllung. Der Dienst setzt updated_since dafür auf den Zeitpunkt, den er sich in Schritt 4 gemerkt hat. So erfasst er auch Ausschreibungen, die seit Beginn der Erstbefüllung aus den Filtern gefallen sind. Ab der zweiten Nacht gilt das größte lastModified des vorigen Laufs.

Die procuris-ID entscheidet, was mit einem Datensatz geschieht. Gibt es sie im CRM, zieht der Dienst die Chance nach den Regeln aus Schritt 7 nach. Gibt es sie nicht, prüft er selbst, ob der Datensatz zu den Filtern der Zieladresse passt, zum Beispiel über cpvClassifications und regionCodes. Passt er, legt der Dienst die Chance an wie in Schritt 6, eine archivierte gleich mit Status. So kommen auch Ausschreibungen ins CRM, deren Nachricht verloren gegangen ist. Alle übrigen Datensätze übergeht er.

Am Ende des Laufs speichert er das größte lastModified als Stand für die nächste Nacht. Liefert ein Lauf nichts, bleibt der gespeicherte Stand unverändert. Der Abruf ohne Filter holt jede geänderte Ausschreibung des Bestands und braucht darum mehr Abrufe als ein gefilterter, siehe Filter und Takt.

Lücken schließen

Verpasste Nachrichten holen Sie je nach Alter auf verschiedenen Wegen nach. procuris verwirft eine Nachricht, wenn auch der zehnte Versuch scheitert, gut drei Tage nach dem ersten. Verworfene Nachrichten meldet procuris der Inhaberin in einer Sammelmail, einmal am Tag, siehe Zustellung und Sicherheit.

  • Nachrichten der letzten 7 Tage sendet die Inhaberin unter Webhooks bei der Zieladresse erneut. Das gilt für beide Varianten.
  • Ältere Lücken bei tender.* holt nur ein System mit API-Zugang über updated_since nach. In Variante A erledigt das der nächtliche Abgleich aus Schritt 9. In Variante B ohne API bleibt eine solche Lücke offen.
  • Ältere search.hit lassen sich nicht nachholen, weil die API keine Passung und keine Suchaufträge kennt.

Felder zuordnen

Ereignisse tragen die Ausschreibung mit den Feldern der API. Sie steht unter data.tender. Die Werte im Hinweis stammen aus dem Musterdatensatz des Datenmodells.

Feld in der NachrichtTypisches Feld im CRMHinweis
data.tender.idprocuris-IDeindeutig, erkennt dieselbe Ausschreibung wieder, siehe Dubletten vermeiden
data.tender.lastModifiedprocuris-StandZeitpunkt der letzten inhaltlichen Änderung bei procuris, in UTC
data.tender.titleName der Verkaufschance„Nordhausen - Sanierung Rolandbrunnen, Erneuerung Brunnentechnik“
data.tender.urlLinköffentliche Seite der Bekanntmachung
data.tender.organizations[] mit role gleich contractingPartyAccount oder Geschäftspartnerid in „procuris-Organisation“, dazu name, address, email, phone
data.tender.organizations[].contactNameKontaktperson am Accountkann null sein oder eine Stelle statt einer Person nennen, im Muster „Vergabestelle“
data.tender.submissionDateAbschlussdatumAngebotsfrist in UTC, im Muster nach der Verschiebung der 14. Oktober 2026, 08:00 UTC
data.tender.participationDeadlinezweites Datumsfeld, zum Beispiel „Teilnahmefrist“nur bei zweistufigen Verfahren gesetzt
data.tender.contractAmount.valueBetragohne Umsatzsteuer, in contractAmount.currency. Im Muster 351.000 Euro.
data.tender.contractAmount.estimatedHinweis „Betrag geschätzt“bei true, weil die Vergabestelle keinen Wert veröffentlicht hat
data.tender.cpvClassifications[0].titleKategorieDie Liste kann leer sein, dann bleibt die Kategorie leer.
data.tender.tenderNumberReferenzVergabenummer, im Muster „33/61/2026“
data.tender.lots[]Positionen oder Unterchancenje Los lotNumber, title, contractAmount
data.fit (nur search.hit)PassungPassung von 0 bis 100
timestamp (nur search.hit)Passung vomZeitpunkt der Passung, entscheidet in Schritt 7 über das Überschreiben

Fehlende Werte bleiben leer oder bekommen einen Ersatz. Ist submissionDate gleich null und verlangt Ihr CRM ein Abschlussdatum, setzen Sie publicationDate plus 30 Tage und markieren Sie die Chance mit „Frist offen“. Sobald die Vergabestelle eine Frist nennt, kommt tender.updated mit submissionDate in changedFields. Ist contractAmount gleich null, lassen Sie den Betrag leer.

Status abbilden

archiveReasonStatus im CRM
expiredverloren oder geschlossen, wenn kein Angebot abgegeben wurde
cancelledverloren oder geschlossen, Grund „aufgehoben“
awardedan Dritte vergeben, wenn Ihr Angebot nicht gewonnen hat
mergedGibt es die Chance zu mergedInto, beide zusammenführen. Fehlt der bleibende Datensatz im CRM: Mit API-Zugang (Variante A) holt der Dienst ihn mit GET /v1/tenders/{mergedInto} und legt die Chance daraus an. Ohne API-Zugang (Variante B) schließt er die alte Chance und vermerkt mergedInto an ihr. Die Chance zur bleibenden Ausschreibung entsteht erst, wenn sie Treffer eines gewählten Suchauftrags ist und ein Ereignis zu ihr kommt.

Dubletten vermeiden

Die procuris-ID verhindert doppelte Chancen zu derselben id. Ein Datensatz je Ausschreibung ist bei procuris das Ziel, keine Garantie. Erscheint eine Bekanntmachung auf mehreren Portalen, führt procuris sie zu einem Datensatz zusammen. Erkennt procuris eine Dublette erst später, archiviert es den jüngeren Datensatz mit archiveReason gleich merged und nennt in mergedInto die id des Datensatzes, der bestehen bleibt. Ihr Dienst behandelt das nach der Zeile merged in der Tabelle oben.

Rezept 2: Nächtlicher Abgleich ins ERP

Im ERP wird jede passende Ausschreibung ein Angebotsprojekt. Passend heißt hier: Sie passt zu Ihren Filtern. In SAP ist das zum Beispiel ein Projekt oder ein Vertriebsbeleg der Art Angebot. Daran hängen Frist als Termin, Auftraggeber als Geschäftspartner und Auftragswert als geplanter Umsatz.

Ein nächtlicher Abruf über die API reicht hier. Planung und Auswertung kommen mit dem Stand vom Vortag aus. Häufigere Abrufe sind möglich. procuris liefert jedoch höchstens einen neuen Stand je Stunde.

Erstbefüllung. Ein Ladelauf ruft GET /v1/tenders mit Ihren Filtern ab und legt je Datensatz ein Projekt an, über id als Schlüssel.

Nächtlicher Lauf. Er ruft mit updated_since gleich dem größten lastModified des vorigen Laufs ab. Es kommen neue, geänderte und archivierte Ausschreibungen. Archivierte schließt er im ERP ab oder führt sie zusammen, nach der Tabelle unter Status abbilden.

Herausgefallene Ausschreibungen behalten im gefilterten Lauf den alten Stand. Sollen sie im ERP aktuell bleiben, ruft der Lauf ohne inhaltliche Filter ab, wie Schritt 9 in Rezept 1. Der Ablauf im Einzelnen steht unter Filter und Takt, alle Felder im Datenmodell.

Verwandte Seiten

Angebot anfordern

Schildern Sie uns, was Sie nutzen oder anbinden möchten. Ihr Angebot richtet sich nach diesem Umfang.

Angebot anfordern

Auf dieser Seite