npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@t4dt/procuros-api-client

v2.0.0

Published

TypeScript client for the Procuros REST API v2

Readme

@t4dt/procuros-api-client

Kleiner TypeScript-HTTP-Client für die Procuros REST API v2. Läuft über fetch (Node 18+), ohne n8n – geeignet für eigene Services, Worker und Tests.

Geschäftsdaten (Bestellungen, Rechnungen, content in Listen) sind als TypeScript-Typen modelliert (Order, Invoice, SentTransaction, …). Umschlag, Queries und Steuer-Bodies bleiben ebenfalls strikt typisiert. Die Laufzeit-Antwort der API wird weiterhin geparst und an eure Typen übergeben – für harte Laufzeit-Garantien könnt ihr zusätzlich validieren (z. B. Zod).

Für Coding-Agenten (Cursor, Codex, …): Siehe AGENTS.md (Englisch, kompakte Referenz inkl. Endpoint-Tabelle und Pagination).

Installation

npm install @t4dt/procuros-api-client
pnpm add @t4dt/procuros-api-client

Grundkonfiguration

| Option | Pflicht | Beschreibung | |--------|---------|----------------| | baseUrl | ja | Basis-URL ohne abschließenden Slash, z. B. https://api.procuros.io | | apiToken | ja | Bearer-Token für API v2 | | fetchImpl | nein | Eigene fetch-kompatible Funktion (Tests, ältere Runtimes ohne globales fetch) |

Ohne globales fetch und ohne fetchImpl wirft der Konstruktor einen synchronen Error (Hinweis auf fehlendes fetch).

import { ProcurosApiClient } from '@t4dt/procuros-api-client';

const client = new ProcurosApiClient({
	baseUrl: 'https://api.procuros.io',
	apiToken: process.env.PROCUROS_TOKEN!,
});

Fehlerbehandlung

Bei HTTP-Fehlerstatus (nicht 2xx) oder Netzwerk-/Transportfehlern wird ProcurosApiError geworfen:

  • message – lesbare Zusammenfassung (u. a. verschachteltes API-error, message im JSON, Fallback mit Statuscode).
  • statusCode – HTTP-Status bei fehlgeschlagener Antwort; undefined, wenn kein normales HTTP-Ergebnis vorlag (z. B. DNS, Timeout).
  • responseBody – geparstes JSON (object/array/…), bei Parsefehler String, bei leerem Body oft undefined.
import { ProcurosApiClient, ProcurosApiError } from '@t4dt/procuros-api-client';

try {
	await client.ping();
} catch (e) {
	if (e instanceof ProcurosApiError) {
		console.error(e.statusCode, e.responseBody);
	}
	throw e;
}

Für die Interpretation typischer Fehlerlasten gibt es Hilfstypen (ValidationErrorBody, … in types.ts). Die API kann darüber hinaus Felder liefern; zur Laufzeit bleibt responseBody bewusst unknown-kompatibel über ProcurosApiError.

Methodenübersicht (REST v2)

| Methode | HTTP | Pfad (relativ zu baseUrl) | |---------|------|------------------------------| | ping() | GET | /v2/ping | | listIncomingTransactions(query) | GET | /v2/transactions | | sendTransaction(body) | POST | /v2/transactions | | markTransactionProcessed(id, body) | PUT | /v2/transactions/{id} | | bulkMarkTransactionsProcessed(body) | POST | /v2/transactions/bulk/mark-processed | | listAllTransactions(query) | GET | /v2/all-transactions | | showTransaction(id) | GET | /v2/all-transactions/{id} | | reportOutgoingError(body) | POST | /v2/errors |

Transaktions-IDs in Pfaden werden intern URL-kodiert.

Pagination (Listen)

listIncomingTransactions und listAllTransactions liefern u. a. hasMore, nextCursor, perPage, count.

  1. Erste Seite: Aufruf ohne cursor (optional per_page und Filter setzen).
  2. Solange hasMore und nextCursor: erneut aufrufen mit cursor: nextCursor (Filter und per_page bei Bedarf unverändert lassen).

Query-Parameter entsprechen der API, u. a. filter[type], filter[flow], filter[status], filter[created_between], per_page, cursor – siehe Typen ListTransactionsQuery und ListAllTransactionsQuery sowie die Procuros-Dokumentation zum exakten Format von filter[created_between].

Beispiele

Die folgenden Snippets setzen einen ProcurosApiClient voraus (siehe Grundkonfiguration).

Ping und eingehende Transaktionen

Jede Zeile in items ist ein ReceivedTransaction: das Feld type bestimmt die Form von content (z. B. bei 'ORDER' ein Order).

await client.ping();

const page1 = await client.listIncomingTransactions({ per_page: 50 });
const page2 = await client.listIncomingTransactions({
	per_page: 50,
	cursor: page1.nextCursor ?? undefined,
});

for (const tx of page1.items) {
	switch (tx.type) {
		case 'ORDER':
			console.log(tx.content.header.orderIdentifier);
			break;
		case 'INVOICE':
			console.log(tx.content.header.invoiceIdentifier);
			break;
		default:
			break;
	}
}

Ausgehend senden (sendTransaction)

Der Body ist ein SentTransaction: immer type (z. B. 'ORDER') plus passend typisiertes content (Order, Invoice, …). Die Typen folgen der OpenAPI-/Procuros-Spezifikation; weicht die Live-API ab, hat die Dokumentation Vorrang – ggf. Paket aktualisieren oder bei Bedarf mit Assertion arbeiten.

Rückgabe: Promise<SendTransactionResult> mit SendTransactionResponse oder SendTransactionAcceptedResponse (z. B. asynchrone Annahme mit message). Enge mit typeof (result as { message?: string }).message === 'string' (siehe AGENTS.md) oder eigener Hilfsfunktion.

import type { SendTransactionResult, SentTransaction } from '@t4dt/procuros-api-client';

// client wie unter „Grundkonfiguration“

const order: SentTransaction = {
	type: 'ORDER',
	content: {
		header: {
			buyer: { identifiers: [{ identifier: '1100001016310', domain: 'GS1' }] },
			supplier: { identifiers: [{ identifier: '1100001016312', domain: 'GS1' }] },
			orderIdentifier: 'PO9383-R46',
			orderDate: '2021-09-30T00:00:00.000000Z',
			currency: 'EUR',
		},
		items: [
			{
				lineNumber: 1,
				identifiers: [{ identifier: '4300348765432', domain: 'GS1' }],
				isDepositItem: false,
				quantity: 20,
				unitOfMeasure: 'EA',
			},
		],
	},
};

const result: SendTransactionResult = await client.sendTransaction(order);

Eingehend als verarbeitet markieren

await client.markTransactionProcessed('…procuros-transaction-id…', {
	success: true,
});

Bulk mark processed

await client.bulkMarkTransactionsProcessed({
	items: [
		{ procurosTransactionId: 'id-1', success: true },
		{ procurosTransactionId: 'id-2', success: false, errorReason: '…', errorType: 'DATA' },
	],
});

Alle Transaktionen filtern und Einzelabruf

listAllTransactions / showTransaction liefern Transaction: zusätzlich zu type und content enthält jeder Eintrag status, flow und createdAt.

const all = await client.listAllTransactions({
	'filter[flow]': 'LIVE',
	'filter[status]': 'PENDING',
	per_page: 25,
});

const first = all.items[0];
if (first?.type === 'SHIPPING_NOTICE') {
	console.log(first.content.header.shippingNoticeIdentifier);
}

const one = await client.showTransaction(all.items[0]!.procurosTransactionId);
if (one.data.type === 'ORDER') {
	console.log(one.data.content.items.length);
}

Ausgehenden Fehler melden

await client.reportOutgoingError({
	errorReason: 'Mapping failed',
	errorType: 'DATA',
	errorContext: { field: 'lineItems[0].quantity' },
});

Tests mit injiziertem fetch

const client = new ProcurosApiClient({
	baseUrl: 'https://api.example.test',
	apiToken: 'test-token',
	fetchImpl: async (url, init) => ({
		ok: true,
		status: 200,
		text: async () => '',
	}),
});

await client.ping();

Exportierte Typen und Konstanten

Aus dem Paket-Entry kommen u. a.:

  • Umschlag & Listen: ListReceivedTransactionsResponse, ListAllTransactionsQuery, SendTransactionResult, …
  • Transaktionen: SentTransaction, ReceivedTransaction, Transaction, TransactionContent
  • Dokumente & Bausteine: Order, OrderResponse, Invoice, CreditNote, ShippingNotice, Party, Tax, … (Modul src/domain, alles wird über types/index re-exportiert)
  • API-Enums: TransactionType, TransactionFlow, TransactionStatus, ErrorType sowie Konstanten TRANSACTION_TYPES, TRANSACTION_FLOWS, TRANSACTION_STATUSES, ERROR_TYPES
  • Weitere Domänen-Enums: z. B. UNIT_OF_MEASURES, MODE_OF_TRANSPORTS, ORDER_RESPONSE_HEADER_TYPES (siehe src/domain/enums.ts)

Für generische JSON-Hilfen (z. B. eigene Erweiterungen): JsonObject, JsonValue aus demselben Entry.

Lizenz

MIT