Urban Sharing - SAP BUBI API (8.0.0)

Download OpenAPI specification:

REST-to-SOAP proxy that integrates the BUBI bike-sharing system with BKK's SAP R/3 ECC 6.0 ERP. Exposes a JSON REST API and translates requests to WSDL-based SOAP web service calls.

SD interface — Submits billing line items to SAP Sales and Distribution. SAP creates an SD Order, generates an Invoice, reports to the NAV online invoice data service, and books the invoice to the customer account. Hungarian law requires an invoice at the time of BUBI service usage, regardless of payment success.

NAV interface — Validates Hungarian tax numbers against the National Tax and Customs Administration (NTCA) database and returns the legal entity's official registered name and address. Pre-validation is mandatory; NAV rejects invalid data during online invoice reporting.

Release History

DateVersionNotes
Tue Sep 29 20268.0.0SD: POST /credit-note invoice type is resolved per SAP line: the first correction of a line over its full quantity is "3", any other correction is "2" (including one that brings the line to zero). A request mixing both is rejected with MIXED_INVOICE_TYPES and is never split
SD: POST /credit-note accepts `correction` { reference, kind REFUND|VOID, originalInvoiceId, expectedInvoiceType? }; reference maps to Dummy3 and the idempotency key `sd:idempotency:v4:REFUND:`. `paymentRefund` is deprecated and maps to a REFUND correction with reference String(paymentRefund.id) (same idempotency key as before)
SD: correction items are matched to SAP lines by productExternalSKU and itemPrice (required with `correction`), so the same SKU at two prices no longer fails as ambiguous; quantities may have up to 3 decimals
SD: line amounts are rounded half to even in whole forints; Itemamount is the sum of the rounded line amounts
Breaking: POST /credit-note responds with SdCreditNoteResponse, adding reference, invoiceType, totalAmount (minor HUF units) and lines, also on SAP_REJECTED
SD: POST /credit-note/preview — dry run returning invoice type, lines and totalAmount without calling SAP; VOID without items returns one group per invoice type ("3" first)
Breaking: GET /refund-items returns one entry per SAP line (itemNumber, originalQuantity, previouslyCorrected added) and accepts optional originalInvoiceId; the ambiguous-SKU 400 is removed
Correction errors return { statusCode, errorCode, message, details.lines } (400; 404 for ORIGINAL_INVOICE_NOT_FOUND)
Thu Jul 30 20267.8.1SD: GET /refund-items items now include itemPrice (minor HUF units, same as POST /invoice itemPrice)
Thu Jul 30 20267.8.0SD: GET /refund-items — returns per-SKU refunded and refundable quantities for a transmitted ORDER or INVOICE document
Tue Jul 28 20267.7.0SD: POST /invoice auto-sets Invoicetype "4" (subsequent payment) when a transmitted audit-log row already exists for the same INVOICE documentId with a different paymentTransaction.externalId; overrides.invoiceType still wins
Breaking (idempotency): SD invoice idempotency key bumped to v4 — includes externalId (`sd:idempotency:v4:documentType:documentId:externalId`) so distinct payment attempts for the same document do not collide
Mon Jul 27 20267.6.0Breaking: POST /invoice removed `paymentTransaction.originalInvoiceId` and `paymentTransaction.isFullyRefunded`; refunds use POST /credit-note
SD: POST /credit-note — rebuilds corrective/cancellation invoices from transmitted audit-log rows for a prior invoice (`invoiceId`), matching refund items by `productExternalSKU` and overriding quantity; SAP INVOICETYPE "2"/"3" is derived from cumulative refunds against the original invoice and prior credit notes
SD: original invoice lookup for credit notes accepts transmitted invoicetype "1" or "4", preferring "4" when both exist
Mon Jun 22 20267.5.1Breaking (idempotency): SD invoice idempotency key bumped to v3 — includes Invoicetype (`sd:idempotency:v3:documentType:documentId:invoicetype`); type "1" and "4" for the same document no longer collide
Mon Jun 22 20267.5.0SD: documented production Invoicetype "4" (SUBSEQUENT_PAYMENT) — payment received for a previously-issued unpaid invoice; set via overrides.invoiceType when core retries after collection_failed → paid
SD: overrides.invoiceType description updated to include "4" alongside "1"/"2"/"3"
Tue May 19 20267.4.0SD: paymentTransaction.externalId maxLength increased to 32 characters and maps to AuthId only (unless overrides.authId is set); TransId is now constant "1"
Tue May 19 20267.3.0SD: paymentTransaction.documentType/documentId now map to SAP Dummy2/Dummy3; Dummy2 values are "P" (order), "O" (invoice), and "R" (refund when originalInvoiceId is set)
Fri Apr 10 20267.2.0SD: optional overrides.authId restored; SAP AuthId is overrides.authId when set, otherwise paymentTransaction.externalId (TransId remains externalId)
Fri Apr 10 20267.1.0SD: optional paymentTransaction.isFullyRefunded (boolean): with originalInvoiceId, false maps to INVOICETYPE "2" (partial refund), true or omitted maps to "3" (full refund)
Fri Apr 10 20267.0.0Breaking: overrides.authId removed; SAP AuthId is always paymentTransaction.externalId (same as TransId; no appended "1")
SD: idempotency cache keys for SD change for the same payload vs releases before this until TTL expires
Thu Apr 09 20266.0.0Breaking: paymentTransaction.refundedTransactionId removed; use originalInvoiceId (string, optional, max 10) — the SAP invoiceId from the original POST /invoice response
SD: Originalinvoicenumber now carries that SAP invoice number; INVOICETYPE remains "1" invoice / "2" corrective / "3" cancellation (char1), with "3" inferred when originalInvoiceId is set unless overrides.invoiceType is provided
Fri Mar 27 20265.0.2SD: POST /invoice now applies idempotency on selected SAP business fields (Id, AuthId, TransId, Invoicetype), reusing the same successful SAP response for duplicates
Thu Mar 26 20265.0.1SD: SAP ZbubiIf BankCard now receives `paymentTransaction.last4` as four characters (no asterisk padding)
Thu Mar 26 20265.0.0Breaking: POST /invoice removed top-level authIdOverride; use overrides.authId instead
SD: optional overrides object on POST /invoice with authId and invoiceType for SAP ZbubiIf (integration / negative testing)
Mon Mar 23 20264.0.0Breaking: NAV lookup endpoint moved from GET /company/info to GET /legal-entity/info
Breaking: NAV DTO/schema names renamed from NavGetCompanyInfo* to NavGetLegalEntityInfo*
Mon Mar 23 20263.0.0Breaking: POST /invoice now requires `user` in the request body
Breaking: POST /invoice request field `company` renamed to `legalEntity`
Sat Mar 21 20262.1.0SD: optional authIdOverride on POST /invoice body to override SAP AuthId
SD: salesOrderId in POST /invoice response extracts the numeric id when SAP EReturn is like "Sales order:0015537378"
Fri Mar 20 20262.0.0Breaking: paymentTransaction.id is number (1–9999999999), not string
Breaking: refundedTransactionExternalId removed; use refundedTransactionId (number, optional) for storno
Breaking: documentId and documentType removed (SAP Dummy1/Dummy2 no longer populated)
SD: Itemprice and Itemamount sent as whole-forint strings (minor HUF units ÷ 100, no .00 fraction)
Validation: last4 must be exactly 4 characters
SD: SAP Invoicetype uses numeric codes ("1" invoice, "2" corrective, "3" cancellation/storno)
Thu Mar 19 20261.2.0NAV taxpayer validation interface (GET /company/info)
Health check integration: SAP SOAP client readiness on /healthz
Version indicator: running commit SHA on /healthz
Wed Mar 18 20261.1.0Structured SD request DTOs with validation
SOAP connectivity: local WSDL files, TLS certificate handling
Internal auth guard
Fri Mar 13 20261.0.0SD invoicing interface (POST /invoice)
Basic SOAP-to-REST proxy for ZbubiWs
Prometheus metrics for SD requests

audience

sap-bubi-api

Sync Log

Query SAP BUBI outgoing request log (JSON, paginated)

Returns a paginated list of outgoing SOAP request rows ordered by dispatched_at DESC. Use filters to narrow by status, date range, invoice ID, document, or SAP field values.

query Parameters
dispatchedAtFrom
string

Filter dispatched_at >= this ISO timestamp

dispatchedAtTo
string

Filter dispatched_at <= this ISO timestamp

status
string
Enum: "TRANSMITTED" "SAP_REJECTED" "TRANSPORT_ERROR" "IDEMPOTENCY_REPLAY"

Filter by outcome status

invoiceId
string

Filter by SAP invoice ID

authId
string

Filter by SAP AUTH_ID

posCode
string

Filter by SAP POS_CODE

invoicetype
string

Filter by SAP INVOICETYPE — 1=standard, 2=partial refund, 3=full refund

matnr
string

Filter by SAP MATNR — material number

userId
string

Filter by SAP USER_ID

bankCard
string

Filter by SAP BANK_CARD — last 4 digits

emailAddress
string

Filter by SAP EMAIL_ADDRESS

eStatus
string

Filter by SAP EStatus — "O" = success, "E" = error

documentType
string (SyncLogDocumentType)
Enum: "ORDER" "INVOICE" "REFUND"

Filter by document type

documentId
string

Filter by document ID

dummy2
string

Filter by SAP DUMMY_2 — document category (e.g. P=pass purchase, R=refund)

dummy3
string

Filter by SAP DUMMY_3 — linked document ID

page
number
Default: 1

Page number (1-based)

limit
number
Default: 100

Page size

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "total": 1042
}

Export SAP BUBI outgoing request log as BKK 3.0 CSV (streamed)

Streams all matching rows as a UTF-8 CSV in the BKK 3.0 column layout (39 columns, A–AM). Filter by status != TRANSMITTED to get the unsynchronised data view. Rows are ordered by dispatched_at ASC. Large result sets are batched internally.

query Parameters
dispatchedAtFrom
string

Filter dispatched_at >= this ISO timestamp

dispatchedAtTo
string

Filter dispatched_at <= this ISO timestamp

status
string
Enum: "TRANSMITTED" "SAP_REJECTED" "TRANSPORT_ERROR" "IDEMPOTENCY_REPLAY"

Filter by outcome status

invoiceId
string

Filter by SAP invoice ID

authId
string

Filter by SAP AUTH_ID

posCode
string

Filter by SAP POS_CODE

invoicetype
string

Filter by SAP INVOICETYPE — 1=standard, 2=partial refund, 3=full refund

matnr
string

Filter by SAP MATNR — material number

userId
string

Filter by SAP USER_ID

bankCard
string

Filter by SAP BANK_CARD — last 4 digits

emailAddress
string

Filter by SAP EMAIL_ADDRESS

eStatus
string

Filter by SAP EStatus — "O" = success, "E" = error

documentType
string (SyncLogDocumentType)
Enum: "ORDER" "INVOICE" "REFUND"

Filter by document type

documentId
string

Filter by document ID

dummy2
string

Filter by SAP DUMMY_2 — document category (e.g. P=pass purchase, R=refund)

dummy3
string

Filter by SAP DUMMY_3 — linked document ID

page
number
Default: 1

Page number (1-based)

limit
number
Default: 100

Page size

Responses

SAP

Create SAP SD invoice

Submits billing line items to the SAP SD SOAP endpoint. SAP creates an SD Order, generates an Invoice, reports to NAV, and books the invoice to the customer account. For documentType INVOICE, when a transmitted audit-log row already exists for the same documentId with a different paymentTransaction.externalId, SAP INVOICETYPE is set to "4" (subsequent payment) unless overrides.invoiceType is provided.

Request Body schema: application/json
required
required
object

Common payment transaction data.

id
required
number

Internal Urbansharing ID of the payment transaction Corresponds to paymentTransaction.id. Used for audit logging only — not sent to SAP (the SAP Id field is sent as the constant "1").

externalId
required
string <= 32 characters

External ID from the Urbansharing payment system. Corresponds to paymentTransaction.externalId. Maps to SAP SOAP field: AuthId (ZbubiIf) unless overrides.authId is set on the invoice request. TransId is sent as the constant "1".

posCode
required
string <= 8 characters

POS terminal ID number in the BUBI system. Maps to SAP SOAP field: PosCode (ZbubiIf).

processedAt
required
string <date-time>

Timestamp when the transaction was processed in the Urbansharing system. Maps to SAP SOAP fields: ServDat (date part, YYYY-MM-DD) and Time (time part, HH:mm:ss) (ZbubiIf).

customerRef
required
string <= 16 characters

Customer reference in the Urbansharing payment system (corresponds to Customer entity). Maps to SAP SOAP field: UserId (ZbubiIf).

emailAddress
required
string <= 70 characters

Customer email address for e-invoice delivery. Maps to SAP SOAP field: EmailAddress (ZbubiIf).

last4
required
string = 4 characters

Last 4 digits of the payment card used in the Urbansharing transaction. Maps to SAP SOAP field: BankCard (ZbubiIf), sent as-is (four characters).

documentType
required
string
Enum: "ORDER" "INVOICE" "REFUND"

Document type mapped to SAP SOAP field Dummy2 via SdDocumentType. A "P" for pass purchases (Orders), an "O" for other products (Invoices). Mapping: ORDER -> "P", INVOICE -> "O". Refunds use POST /credit-note.

documentId
required
number

Document ID (e.g. order id). Maps to SAP SOAP field Dummy3 (max 40 characters).

required
Array of objects (SdItem)

Array of billing line items.

Array
productExternalSKU
required
string <= 4 characters

Product external SKU from the Urbansharing core database (corresponds to Product.externalSKU). Maps to SAP SOAP field: Matnr (ZbubiIf).

quantity
required
number

Quantity of purchased items. Maps to SAP SOAP field: Quant (ZbubiIf), converted to string.

itemPrice
required
number

Gross unit price in 1/100 of a Hungarian forint (Urbansharing minor HUF units). Maps to SAP SOAP field: Itemprice (ZbubiIf) as whole forints, e.g. 100000 -> "1000".

validFrom
string <date-time>

Beginning of validity period (date and time). Maps to SAP SOAP field: ValFrom (ZbubiIf), formatted as yyyyMMddHHmmss.

validTo
string <date-time>

End of validity period (date and time). Maps to SAP SOAP field: ValTo (ZbubiIf), formatted as yyyyMMddHHmmss.

object

Optional overrides for SAP ZbubiIf fields (e.g. Invoicetype). Intended for advanced scenarios and integration / negative testing.

authId
string <= 32 characters

Override for the SAP authorization / idempotency code. When omitted, AuthId is derived as paymentTransaction.externalId. Maps to SAP SOAP field: AuthId (ZbubiIf).

invoiceType
string <= 1 characters

Override for SAP Invoicetype (char1). Allowed production values are typically "1" (invoice), "2" (corrective / partial refund), "3" (full refund), "4" (subsequent payment for a previously-issued unpaid invoice). Other values may be used to exercise SAP validation (e.g. negative tests). When omitted, type defaults to "1", or to "4" when documentType is INVOICE and a transmitted audit-log row already exists for the same documentId with a different paymentTransaction.externalId. Refunds use POST /credit-note. Maps to SAP SOAP field: Invoicetype (ZbubiIf).

required
object

Private individual customer data.

name
required
string <= 70 characters

Private individual's full name. Maps to SAP SOAP field: Name1 (ZbubiIf).

country
required
string <= 3 characters

Country code from SAP country master data. Maps to SAP SOAP field: Country (ZbubiIf).

postCode
required
string <= 10 characters

ZIP/postal code of the customer. Maps to SAP SOAP field: PostCode1 (ZbubiIf).

city
required
string <= 40 characters

City/place of the customer. Maps to SAP SOAP field: City1 (ZbubiIf).

street
required
string <= 60 characters

Street and house number of the customer. Maps to SAP SOAP field: Street (ZbubiIf).

object

Legal entity customer data.

taxNumber
required
string <= 13 characters

Legal entity tax number (format: XXXXXXXX-X-XX; corresponds to LegalEntity.taxNumber in the B2B module). Validated against the NAV database. Maps to SAP SOAP field: TaxNumber (ZbubiIf).

groupTaxNumber
string <= 13 characters

Legal entity group tax number (format: XXXXXXXX-X-XX; corresponds to LegalEntity.groupTaxNumber in the B2B module). Maps to SAP SOAP field: GroupTaxNumber (ZbubiIf).

name
required
string <= 70 characters

Legal entity name in the Urbansharing system (corresponds to LegalEntity.name in the B2B module). Maps to SAP SOAP field: LegalEntityBillingName (ZbubiIf).

country
required
string <= 3 characters

Legal entity country code (corresponds to LegalEntity.country in the B2B module). Maps to SAP SOAP field: LegalEntityBillingCountry (ZbubiIf).

zipCode
required
string <= 10 characters

Legal entity ZIP/postal code (corresponds to LegalEntity.zipCode in the B2B module). Maps to SAP SOAP field: LegalEntityBillingZip (ZbubiIf).

city
required
string <= 40 characters

Legal entity city (corresponds to LegalEntity.city in the B2B module). Maps to SAP SOAP field: LegalEntityBillingCity (ZbubiIf).

address
required
string <= 60 characters

Legal entity address (corresponds to LegalEntity.address in the B2B module). Maps to SAP SOAP field: LegalEntityBillingAddress (ZbubiIf).

Responses

Request samples

Content type
application/json
{
  • "paymentTransaction": {
    },
  • "items": [
    ],
  • "overrides": {
    },
  • "user": {
    },
  • "legalEntity": {
    }
}

Response samples

Content type
application/json
{
  • "salesOrderId": "0015537378",
  • "invoiceId": "9215538727",
  • "errorType": "SAP_REJECTED",
  • "errorMessage": "Duplicate invoice number"
}

Preview SAP SD credit note

Dry run of POST /credit-note: resolves the invoice type, lines and amounts without calling SAP or writing to the audit log. totalAmount is the amount to refund. VOID without items returns one group per invoice type ("3" first); submit each group as a separate correction.

Request Body schema: application/json
required
originalInvoiceId
required
string <= 10 characters

SAP invoice number of the original posting.

kind
required
string
Enum: "REFUND" "VOID"
Array of objects (SdCorrectionItem)

Items to correct. Required for REFUND. For VOID without items, every line with a remaining quantity is cancelled in full, split into one group per invoice type.

Array
productExternalSKU
required
string <= 4 characters

Product external SKU from the Urbansharing core database (corresponds to Product.externalSKU). Matched against SAP Matnr of the original posting.

itemPrice
number

Gross unit price in 1/100 of a Hungarian forint (Urbansharing minor HUF units), as sent to POST /invoice. Together with productExternalSKU it identifies the SAP line of the original posting. Required with correction; only legacy paymentRefund requests may omit it.

quantity
required
number

Quantity to correct, up to 3 decimal places. Maps to SAP SOAP field: Quant (ZbubiIf).

Responses

Request samples

Content type
application/json
{
  • "originalInvoiceId": "9215538727",
  • "kind": "REFUND",
  • "items": [
    ]
}

Response samples

Content type
application/json
{
  • "groups": [
    ]
}

Create SAP SD credit note

Rebuilds a corrective ("2") or cancellation ("3") posting from the original SAP posting in the audit log. Items are matched to SAP lines by productExternalSKU and itemPrice. Per line, the first correction over the full quantity is "3"; any other correction is "2". Requests mixing both are rejected with MIXED_INVOICE_TYPES.

Request Body schema: application/json
required
object

The correction to submit. Exactly one of correction and paymentRefund must be set.

reference
required
string^[A-Za-z0-9-]{1,40}$

Identifier of this correction ("Refund ID" in the admin UI). Refunds use the payment refund id, voids use V-<n>. Maps to SAP SOAP field Dummy3 and is the idempotency key of the request.

kind
required
string
Enum: "REFUND" "VOID"

REFUND corrects the refunded quantities. VOID cancels the full remaining quantity of every line in items.

originalInvoiceId
required
string <= 10 characters

SAP invoice number of the original posting (invoiceId from POST /invoice, INVOICETYPE "1" or "4"). Maps to SAP SOAP field: Originalinvoicenumber (ZbubiIf).

expectedInvoiceType
string
Enum: "2" "3"

Invoice type returned by POST /credit-note/preview. When the resolved type differs (another correction was transmitted in between), the request is rejected with INVOICE_TYPE_MISMATCH.

object
Deprecated

Deprecated: use correction. Maps to a REFUND correction with reference = String(paymentRefund.id); items are matched by productExternalSKU only.

id
required
number

Internal Urbansharing ID of the payment refund Corresponds to paymentRefund.id. Maps to SAP SOAP field Dummy3 (max 40 characters).

originalInvoiceId
required
string <= 10 characters

SAP invoice number of the document being reversed, exactly as returned in invoiceId from the successful POST /invoice response for the original posting (SAP INVOICETYPE "1" standard invoice or "4" subsequent payment). Maps to SAP SOAP field: Originalinvoicenumber (ZbubiIf).

required
Array of objects (SdCorrectionItem)

Items to correct, aggregated by (productExternalSKU, itemPrice). itemPrice is required with correction.

Array
productExternalSKU
required
string <= 4 characters

Product external SKU from the Urbansharing core database (corresponds to Product.externalSKU). Matched against SAP Matnr of the original posting.

itemPrice
number

Gross unit price in 1/100 of a Hungarian forint (Urbansharing minor HUF units), as sent to POST /invoice. Together with productExternalSKU it identifies the SAP line of the original posting. Required with correction; only legacy paymentRefund requests may omit it.

quantity
required
number

Quantity to correct, up to 3 decimal places. Maps to SAP SOAP field: Quant (ZbubiIf).

Responses

Request samples

Content type
application/json
{
  • "correction": {
    },
  • "paymentRefund": {
    },
  • "items": [
    ]
}

Response samples

Content type
application/json
{
  • "salesOrderId": "0015537378",
  • "invoiceId": "9215538727",
  • "errorType": "SAP_REJECTED",
  • "errorMessage": "Duplicate invoice number",
  • "reference": "V-1042",
  • "invoiceType": "3",
  • "totalAmount": 39000,
  • "lines": [
    ]
}

Get refundable quantities by document

Returns one entry per SAP line of the original posting with its refunded and remaining refundable quantities, derived from the audit log and prior credit notes. With originalInvoiceId, the original posting is resolved by invoice id exactly as POST /credit-note does.

query Parameters
documentType
required
string
Enum: "ORDER" "INVOICE" "REFUND"
Example: documentType=ORDER

Business document type for the transmitted SAP invoice (ORDER or INVOICE).

documentId
required
number
Example: documentId=9100000001

Business document ID (e.g. order or invoice id).

originalInvoiceId
string <= 10 characters
Example: originalInvoiceId=9215538727

SAP invoice number of the original posting. When set, the original posting is resolved by invoice id, exactly as POST /credit-note does.

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Get legal entity info from NAV

Validates a Hungarian tax number against the NAV database and returns the official registered legal entity name, address, and group tax number.

query Parameters
taxNumber
required
string = 8 characters
Example: taxNumber=11961552

8-digit Hungarian taxpayer ID to validate against the NAV database.

Responses

Response samples

Content type
application/json
{
  • "valid": true,
  • "taxpayerName": "Peek & Cloppenburg Kft",
  • "taxNumber": "11961552-2-42",
  • "groupTaxNumber": "17782672-5-44",
  • "addresses": [
    ]
}

Clear NAV legal entity cache

Clears cached NAV legal-entity responses. If taxNumber is provided, clears one key. Without taxNumber, clears all legal-entity cache entries.

query Parameters
taxNumber
string = 8 characters
Example: taxNumber=11961552

8-digit Hungarian taxpayer ID. If provided, clears cache only for this tax number.

Responses

Response samples

Content type
application/json
{
  • "scope": "single",
  • "deletedCount": 1
}