NAV

Introduction

Barzahlen API v2 allows you to create payment and refund slips customers can use in stores like supermarkets to pay or receive money. Slips are sent to users as an email with a PDF attachment or as a text message. When a store’s point of sale system confirms the transaction, Barzahlen usually immediately calls a Webhook to notify your system about the payment. You can then use this confirmation e.g. to mark an invoice as paid or trigger shipping goods to the customer.

The API is a JSON-based REST API.

Functionality

Slip Types

Slip States

A slip is in one of four states, all except pending are final.

Identifying a customer

To reduce money laundering, we are required to store an identifier that is unique per customer. Depending on your contract with Barzahlen, this can be an email address or an internal customer identifier. You must provide the identifier in the customer key field. If you provide an email address as customer key, you must use the same email address in the email field.

Accessing the API

The API is accessible via HTTPS and uses JSON as format for requests and responses. As REST-API, it uses different HTTP methods to indicate the type of request and response codes for indicating the outcome of a request. For errors, it returns additional, more specific error classes, codes, and messages.

The API endpoints are:

When accessing the API, always verify the HTTPS server certificate. Certificate verification is necessary to prevent man-in-the-middle attacks. Read your HTTP client’s documentation carefully and, among other required checks, make sure to verify the certificate chain as well as the server name(s) in the certificate.

Sandbox

Sandbox mode allows working on slips that can not actually be paid in a store. Instead, you can use the Control Center to simulate payment and expiry and receive webhooks for these events. Text messages are not sent in sandbox mode, but emails are.

In contrast to the production endpoint, the sandbox endpoint is available immediately after you sign up, so you can begin integrating Barzahlen as soon as possible.

Optional Fields

Authentication

For authentication, the API requires requests to be signed using your API key. You will never have to include your API key in plain text in a request, only as part of the signature. We use the same signature algorithm to sign webhook requests to your system.

For authentication and webhook signature verification, you will need your division id and your payment key. You can find both in the Barzahlen Control Center under Settings / Divisions.

See Accessing the API for information about HTTPS certificate verification.

API Requests

Authorization header format for API requests

Authorization: BZ1-HMAC-SHA256 DivisionId=ID, Signature=SIGNATURE

For requests, the API expects a standard HTTP Authorization header with a custom authentication scheme, BZ1-HMAC-SHA256.

Replace ID with your division’s ID and SIGNATURE with a signature based on certain parts of the request. The algorithm for calculating the signature is described below.

Example Date header

Date: Tue, 15 Nov 1994 08:12:31 GMT

The signature includes the current time, which must be included in the request’s Date header.

When the Authorization header is missing or invalid, the API returns HTTP status 401 with an WWW-Authenticate: BZ1-HMAC-SHA256 header and an error.

Webhook Requests

For webhooks, we provide the signature in a custom header, Bz-Signature.

Bz-Signature header format for webhook requests

Bz-Signature: BZ1-HMAC-SHA256 SIGNATURE

SIGNATURE will be replaced with a signature based on certain parts of the request. The algorithm for calculating the signature is described below. Webhook requests contain a Date header as used in API requests.

When receiving webhooks, always verify the signature.

Calculating the Signature

Calculating the signature means generating a string with certain parameters and then using your division’s payment key to sign the string with HMAC-SHA256. This section describes the signature process and the next section contains a signature generator you can use to verify and debug your implementation.

The string to sign contains parameters in the following order, separated by newlines.

Example String to sign

api.barzahlen.de:443
GET
/v2/slips/slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd

Thu, 31 Mar 2016 10:50:31 GMT

e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

The newlines are always necessary, regardless whether a value is empty or not, so the number of lines in the string to sign is always the same. Do not add a newline after the body digest.

When a value is empty (e.g. an empty query string), you will still have to add the newline.

The last step is signing the string with your payment key. Use the payment key in the form we provide it (do not convert the data to binary, even if it is in hexidecimal form).

Example Key: 6b3fb3abef828c7d10b5a905a49c988105621395

Ruby Example showing HMAC-SHA256 signing

require 'openssl'
signature = OpenSSL::HMAC.hexdigest('sha256', payment_key, string_to_sign)

Use the the payment key to sign the string using HMAC with SHA-256 as hash function and encode the resulting bytes in hexidecimal form.

With the example string and example key above, you can calculate the following signature:

Example Signature: 3ebd7a069c0c0f6aafd537866c2b3af6594878eb62db51e2350bfba396971745

Example Request

Example Request with signature in Authorization header

GET /v2/slips/slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd HTTP/1.1
Authorization: BZ1-HMAC-SHA256 DivisionId=20065, Signature=3b1a28fffd1cd2bbc1ec24cfbca1e85d802159e78c08328d92d4337a4a33b61d
Date: Thu, 31 Mar 2016 10:50:31 GMT
Host: api.barzahlen.de

The example shows an API request including all headers required for authentication.

You can find an example for webhooks in the Webhooks section.

Signature Generator

This signature generator allows you to verify and debug your implementation of API v2’s signature algorithm. When using it, make sure to not have extra whitespace in any of the fields.

Signature

String to Sign









Idempotency

Most methods on resources in Barzahlen API v2 can or even must be used in an idempotent way, so you can automatically retry requests without having unintended side effects.

Retrying requests makes your system more resilient when network failures happen, our system temporarily fails to process your request or your division exceeds the rate limit. We highly recommend implementing automated retries - they are necessary for reliable use of any network-based API.

Here is an overview of the idempotency properties of the different methods and resources:

Using the Idempotency-Key header in any endpoint other than POST /slips has no effect and will be ignored.

Rate Limiting

The API is rate limited per division to ensure that no single division can use too much server resources.

Example API response headers after a single request

HTTP/1.1 200 OK
Content-Length: 363
Content-Type: application/json;charset=utf-8
Date: Tue, 03 May 2016 10:54:54 GMT
Ratelimit-Limit: 31
Ratelimit-Remaining: 30
Ratelimit-Reset-After: 1
Request-Id: 2b48b13ec1994d1e9cc577058c7b3be1

If the limit is reached, additional requests are not processed and a rate_limit_exceeded error is returned with HTTP status code 429. Over time, requests will be allowed again (as indicated by the Retry-After header) and the request can be repeated.

The API uses a ‘leaky bucket’ algorithm for rate limiting. It allows a sustained rate of 1 request per second, i.e. the bucket 'leaks’ one request per second. The bucket has a size of 31, so a divison can execute a burst of 31 requests at once (within one second) before the limit is reached, i.e. the bucket is full. The next request is available after a second, when one request has 'leaked’ from the bucket. Each second, another request 'leaks’ from the bucket until after 31 seconds without requests, the bucket is empty again.

If you expect to reach these limits, you should implement client-side rate limit to prevent getting rate_limit_exceeded errors. When getting such an error, do not immediately retry a request, but wait at least the time indicated by the Retry-After header.

The following rate limiting-related headers are returned:

Webhooks

Example Webhook Request

POST /barzahlen/callback HTTP/1.1
Host: callback.example.com
Date: Fri, 01 Apr 2016 09:20:06 GMT
Bz-Hook-Format: v2
Bz-Signature: BZ1-HMAC-SHA256 eb22cda264a5cf5a138e8ac13f0aa8da2daf28c687d9db46872cf777f0decc04
Content-Type: application/json;charset=utf-8
Content-Length: 414
User-Agent: Barzahlen Notifier

{
    "event": "paid",
    "event_occurred_at": "2016-01-06T12:34:56Z",
    "affected_transaction_id": "4729294329",
    "slip": {
        "id": "slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd",
        "slip_type": "payment",
        "division_id": "1234",
        "reference_key": "O64737X",
        "expires_at": "2016-01-10T12:34:56Z",
        "customer": {
            "key": "LDFKHSLFDHFL",
            "cell_phone_last_4_digits": "6789",
            "email": "john@example.com",
            "language": "de-DE"
        },
        "metadata": {
          "order_id": 1234,
          "invoice_no": "A123"
        },
        "transactions": [
          {
            "id": "4729294329",
            "currency": "EUR",
            "amount": "123.34",
            "state": "paid"
          }
        ]
    }
}

When a transaction is paid or a slip expires, our system does an HTTPS-request on a URL you can specify. You can set the URL up in the Barzahlen Control Center under Settings / Divisions / Notification URL. Alternatively, if you want to use different hook URLs for some of the transactions, you can specify a hook_url when creating a transaction.

A webhook request is done as POST request with a JSON body. The body contains the event that happened (paid or expired), a timestamp when the event occurred and the id of the transaction affected by the event. The body also contains a complete slip resource, so you can access a given reference_key or metadata. When executing webhooks, we do not follow redirects.

Webhook requests are signed in the same way as requests to the API. For hook requests, we provide the signature in the Bz-Signature header. The signature works as authentication, so always verify the signature to prevent unauthorized access. See Authentication for more information about the signature.

The example request is signed using the key 6b3fb3abef828c7d10b5a905a49c988105621395.

We verify the HTTPS server certificate when making webhook requests to your system, so make sure you have a server certificate accepted by common browsers.

The Bz-Hook-Format header contains a version identifier for the webhook format. For slips created via API v2, it always contains v2. For slips previously created using API v1, it contains v1. See Webhook transition for more information on how to migrate webhooks from API v1 to v2.

Failed Requests

If a webhook request fails, we retry the request up to 11 times. The waiting time between retries increases exponentially. After at least 24 hours, we give up and send your Control Center account’s administrator an email. The failed webhook can also be viewed and a retry can be initiated in the Barzahlen Control Center under Transactions / Notifications. For sandbox slips, we do not retry requests (and do not send an email), so they can be viewed immediately in the Control Center.

We regard all HTTP status codes in the 2xx range as success and everything else as an error. This means redirect status codes like 307 are interpreted as error since we do not follow redirects.

Errors

Example Error Response

{
  "error_class": "invalid_parameter",
  "error_code": "invalid_slip_type",
  "message": "slip_type: slip_type is required",
  "request_id": "1865359ad354441b9403c3771d811c53"
}

Barzahlen API v2 returns different HTTP error codes in the 4xx and 5xx ranges. When an error status is returned, the body contains JSON with more information about the error (except for some 5xx errors, which might contain non-JSON data).

Error responses contain an error class as well as an error code. Errors in the same class contain similar types of errors. Your API implementation should be prepared to handle new error codes in any of the existing classes. New error classes will not be added without a new API version. Never write code parsing error messages or use them for anything other than showing them to people. Error messages will change without announcement.

The following describes all error classes as well as all currently used error codes. You should implement automated retries for certain errors, but not for others. Retries are useful not only for certain errors returned by the API, but also for other error cases. See Idempotency for more information.

Error Classes

General Errors

The message returned with an error code can contain additional information.

Status Class Code and hints
401 auth invalid_signature
401 auth invalid_signature_format
401 auth only_sandbox_allowed
400 transport invalid_host_header
413 transport request_body_too_large
405 invalid_format method_not_allowed
429 rate_limit rate_limit_exceeded
400 invalid_format invalid_query_params - Query params are not used at the moment.
404 invalid_format invalid_request_url
500 server_error internal_server_error - These should happen rarely, we fix them as soon as possible.

Other HTTP status codes in the 5xx range (e.g. 503) are possible and should be treated the same as a 500 error.

You can find endpoint-specific error codes with the documentation for each endpoint.

Request-Ids

Example Request-Id header

Request-Id: ea65be86bc594a198579c09f16c32681

If you need help with integrating the API and have questions related to a specific request you made, please let us know the Request-Id header in the response. Error responses also contain the request id in their JSON body.

API Stability

We will make backwards-compatible changes to Barzahlen API v2 without releasing a new version. This means we will not break existing code accessing the API, under the assumption that the existing code allows for the following changes to the API:

If we need to make changes which likely break systems using the API in the future, we will release a new version of the API. Examples for such backwards-incompatible changes are:

Changelog

2016-09-20

2016-09-09

2016-07-29

Note: The shown dates do not necessarily correspond to the date the change was deployed.

Changes from API v1

Compared to API v1, Barzahlen API v2 supports several new features and technical improvements.

New Features

Technical Changes

JSON-based REST API

API v2 is a JSON-based REST API and no longer uses XML. This results in a new structure and different endpoints.

We provide JSON schema definitions for request and response bodies.

New slip identifiers

In API v2, slip ids mostly replace transaction ids. Slip ids are strings with a length of up to 50 bytes, while API v1 transaction ids were numeric ids.

A slip represents a token a customer can use to go into a store and pay money in or to get money paid out. A slip usually is a PDF to be printed or a number in a text message. A transaction represents a possible transfer of money. At the moment, a slip created via API v2 must have exactly one transaction.

We built API v2 in a way to make the transition from transaction ids to slip ids as seamless as possible for existing systems. Slips previously created using API v1 (then called transactions) will keep their numeric transaction id, so you can treat existing transactions the same as transactions created using API v2. You can e.g. fetch information about an API v1 slip using the same endpoint as an API v2 slip, GET /slips/12345, with 12345 being a API v1 transaction id. Slips keeping their identifiers also allows you to easily associate webhooks sent with the API v2 format with previously created transactions.

Transaction ids still exist, although, at the moment, they are only necessary to update attributes in a slip’s transactions field.

Strings as identifiers

Not only API v2’s slip ids are strings, but also transaction and division identifiers are now strings. Although some of the fields might still return only numbers in a string, make sure to treat them as strings with the lengths specified in this documentation. We will change some of the fields to contain non-numeric characters in the future.

Webhook transition

Webhooks in API v2 are always POST requests with a JSON payload.

The old v1 webhook format doesn’t support various fields used in API v2, most importantly slip ids. We thus switch the webhook format to the API v2 format when you create the first slip via API v2.

For slips created via API v2, webhooks are sent in v2 format exclusively. So before using API v2 in production, make sure your production webhooks understand the v2 format.

To allow for a transition period (e.g. during testing), when v2 format is activated, we send webhooks twice for slips created via API v1: Once in v1 format and once in v2 format. This ensures that creating a slip via API v2 doesn’t break webhooks for systems still using API v1 and only supporting v1 webhooks.

If you want to prevent your systems reporting errors due to requests they can’t understand, you can decide to ignore webhooks in a certain format by checking the Bz-Hook-Format header. This can be useful for ignoring v1 webhooks after switching to API v2, when there can still be pending transactions created via API v1 before the switch.

When making API v2 webhook requests, we no longer follow redirects. For transitional API v1 webhook requests, we still do.

Other changes

Customer Checkout

Barzahlen checkout overlay example

Barzahlen provides a custom checkout overlay for each payment slip that has been created using the Barzahlen API v2. You should display this checkout overlay to your customers immediately after they successfully finished their ordering process on your website. (It cannot be displayed for refund slips.)

The Barzahlen checkout overlay allows your customers to:

Setup

Example HTML code to display the Barzahlen checkout overlay

<!-- Barzahlen Checkout -->
<script src="https://cdn.barzahlen.de/js/v2/checkout.js"
        class="bz-checkout"
        data-token="CHECKOUT_TOKEN">
</script>
<!-- End Barzahlen Checkout -->

The checkout overlay is very easy to set up and can be displayed on desktop browsers as well as on mobile phones. All you have to do is the following:

  1. Add the HTML tag <script src="https://cdn.barzahlen.de/js/v2/checkout.js" class="bz-checkout" data-token="CHECKOUT_TOKEN"> to your website’s own checkout page. (This is the page you display to your customers after they have confirmed an order on your website and you received a success response from your request to POST /slips.) You should put the <script ...> tag at the very bottom of your website’s HTML source code just before the closing </body> tag. Otherwise some older browsers might not be able to load it properly.
  2. Place the content of the checkout_token that you received within the API response of your call to POST /slips into the data-token attribute of the <script ...> tag.

The <script ...> tag loads a JavaScript file from https://cdn.barzahlen.de/js/v2/checkout.js which automatically displays the Barzahlen checkout overlay within a modal on top of your website’s own checkout page. The customer is able to close the modal with one click to return to your website.

Reopening the Barzahlen checkout overlay

Allow customers to manually reopen the Barzahlen checkout overlay using a predefined button

<button class="bz-checkout-btn">
  Bezahlen mit Barzahlen
</button>

Reopen the Barzahlen checkout overlay using a custom link

<a href="javascript:bzCheckout.display();">
  Bezahlen mit Barzahlen
</a>

As mentioned above, the Barzahlen checkout overlay will open automatically in a modal on your website. Customers are able to close this overlay with a click on the close icon in the top right corner.

In case customers accidentally close the overlay, they might want to reopen it. To allow them to do this, we provide the following two possibilities:

  1. Include the following code into the HTML of your own checkout page: <button class="bz-checkout-btn">Pay now with Barzahlen.de</button>. This will render a pre-styled button that, when clicked by the customer, reopens the Barzahlen checkout overlay. (Make sure to include the <button ...> on the same page as the <script ...> tag, as it will not work otherwise.)
  2. In case you want to be more flexible (e.g. you want to use your own styled button or a link tag instead) you can reopen the Barzahlen checkout overlay using the JavaScript function bzCheckout.display().

Disable automatic display

Example HTML code to disable the automatic display of the Barzahlen checkout overlay

<!-- Barzahlen Checkout -->
<script src="https://cdn.barzahlen.de/js/v2/checkout.js"
        class="bz-checkout"
        data-token="CHECKOUT_TOKEN"
        data-auto-display="false">
</script>
<!-- End Barzahlen Checkout -->

Under certain circumstances it might be useful to prevent the checkout overlay from appearing automatically. Add the optional attribute data-auto-display="false" to the <script ...> tag to achieve this result. Not specifying the data-auto-display attribute at all or setting it to "true" will automatically display the checkout overlay. We recommend to always display the checkout overlay automatically to make it as easy as possible for your customers to immediately see all relevant information related to their Barzahlen payment process.

If you decide to disable the automatic display, make sure to allow your customers to manually open the checkout overlay using a predefined button or custom link like explained above.

Sandbox

Example HTML code to display the Barzahlen checkout overlay in sandbox mode

<!-- Barzahlen Checkout Sandbox -->
<script src="https://cdn.barzahlen.de/js/v2/checkout-sandbox.js"
        class="bz-checkout"
        data-token="CHECKOUT_TOKEN">
</script>
<!-- End Barzahlen Checkout Sandbox -->

To use the Barzahlen checkout overlay in sandbox mode, you need to change the src parameter of the HTML tag to point to a different JavaScript file: <script src="https://cdn.barzahlen.de/js/v2/checkout-sandbox.js" class="bz-checkout" data-token="CHECKOUT_TOKEN">

/slips

Create Slip

POST /slips

Example Minimal Request Body for a payment slip

{
  "slip_type": "payment",
  "customer": {
    "key": "LDFKHSLFDHFL"
  },
  "transactions": [
    { "currency": "EUR", "amount": "123.34" }
  ]
}

Create a payment or refund slip.

If you provide an email address, we send an email with a PDF attachment to the customer. If you provide a cell phone number for a payment slip, we send a text message containing the barcode number and the amount. We don’t send text messages for refunds.

Note: The Idempotency-Key header is required for this endpoint. See below.

Payment Slips

Payment slips can be paid by a customer and result in money being transferred to your division. They are used e.g. when a customer orders a product in an online shop.

Payment slip specifics:

Refund Slips

Example Minimal Request Body for a refund slip

{
  "slip_type": "refund",
  "refund": {
    "for_slip_id": "slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd"
  },
  "transactions": [
    { "currency": "EUR", "amount": "-23.99" }
  ]
}

Refund slips return money to a customer and must be associated with a payment slip the same customer previously paid. They are used e.g. when a customer has returned a product to an online shop. The sum of all refund slip’s amounts associated with a single payment slip must be less than or equal to the payment slip’s amount.

Refund slip specifics:

Example Request Body

{
  "slip_type": "payment",
  "reference_key": "O64737X",
  "hook_url": "https://psp.example.com/hook",
  "expires_at": "2016-01-10T12:34:56Z",
  "customer": {
    "key": "LDFKHSLFDHFL",
    "cell_phone": "+49123456789",
    "email": "john@example.com",
    "language": "de-DE"
  },
  "show_stores_near": {
    "address": {
      "street_and_no": "Wallstr. 14a",
      "zipcode": "10179",
      "city": "Berlin",
      "country": "DE"
    }
  },
  "metadata": {
    "order_id": 1234,
    "invoice_no": "A123"
  },
  "transactions": [
    {
      "currency": "EUR",
      "amount": "123.34"
    }
  ]
}

Request Attributes

Name Type Description Example
customer:​cell_phone nullable string The customer’s cell phone number in international format. For payment slips, triggers a text message being sent if provided.
Pattern: ^\+[0-9]+$
Length: 9..19
"+49151123456789"
customer:​email nullable string The customer’s email address. Triggers an email being sent if provided.
Length: 3..80
"john@example.com"
customer:​key nullable string A key uniquely identifying the customer. See Identifying a customer for more information.
Pattern: ^[a-zA-Z0-9!"#\$%&'()*+,-\./:;<=>\?@\[\\\]\^_\{\|\}~]+$
Length: 0..80
"LDFKHSLFDHFL"
customer:​language nullable string The language used for communicating with the customer (e.g. for email, text message, web interface). RFC 5646 language-region code, only de-DE is supported at the moment.
One of: null or "de-DE"
"de-DE"
expires_at nullable date-time Time the slip expires and can no longer be used. Will be set automatically depending on your contract if not provided. Format is date-time as defined in RFC 3339 Section 5.6.
Pattern: ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(|\.[0-9]+)(Z|[\+-][0-9]{2}:[0-9]{2})$
"2015-01-01T12:00:00Z"
hook_url nullable uri Per-slip webhook URL to use instead of the one configured in Control Center. See Webhooks.
Pattern: ^https://[a-zA-Z0-9!"#\$%&'()*+,-\./:;<=>\?@\[\\\]\^_\{\|\}~]+$
Length: 0..512
null
metadata nullable object Custom metadata not processed by Barzahlen, returned in responses and webhooks. Useful for associating slips with internal identifiers, see also reference_key. Maximum 3 keys, max. 15 bytes key length and max. 50 bytes value length. Keys and values must be strings. null
reference_key nullable string A key referencing an order or another internal process. Must be unique per payment slip and division (or null).
Pattern: ^[a-zA-Z0-9!"#\$%&'()*+,-\./:;<=>\?@\[\\\]\^_\{\|\}~]+$
Length: 0..40
"O64737X"
refund:​for_slip_id string For refunds, must reference a payment slip’s id. See 'Refund Slips’ above.
Pattern: ^([0-9]+|slp\-[a-z\-0-9]+)$
Length: 1..50
"2738529243"
show_stores_near:​address:​city string The customer’s city for showing nearby stores. See above for more information about providing an address.
Length: 1..50
"Berlin"
show_stores_near:​address:​country string The customer’s country for showing nearby stores, a ISO 3166-1 alpha 2 language code.
Pattern: ^[A-Z]+$
Length: 0..2
"DE"
show_stores_near:​address:​street_and_no string The customer’s street and house number for showing nearby stores.
Length: 1..60
"Wallstr. 14a"
show_stores_near:​address:​zipcode string The customer’s zip code for showing nearby stores.
Pattern: ^\d+$
Length: 0..10
"10123"
slip_type string Slip type, see above.
One of: "payment" or "refund"
"payment"
transactions/​amount string Amount to be paid in/out with a dot as decimal separator and maximum of two decimal places. Negative when paying out money.
Pattern: ^-?[0-9]+\.[0-9]+$
"123.34"
transactions/​currency string Currency as three-letter ISO 4217 code. Only EUR is supported at the moment.
One of: "EUR"
"EUR"

Download JSON schema

Example Response Body for HTTP status 201

{
  "id": "slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd",
  "slip_type": "payment",
  "division_id": "1234",
  "reference_key": "O64737X",
  "hook_url": "https://psp.example.com/hook",
  "expires_at": "2016-01-10T12:34:56Z",
  "customer": {
    "key": "LDFKHSLFDHFL",
    "cell_phone_last_4_digits": "6789",
    "email": "john@example.com",
    "language": "de-DE"
  },
  "checkout_token": "djF8Y2hrdHxzbHAtMTM4ZWI3NzUtOWY5Yy00NzYwLWI4ZTAtYTNlZWNmYjQ5M2IxfElBSThZMnd6SFYwbjJpMm9aSUpvREpnYnhNS3c5Z2x3elJOanlLblZJeFk9",
  "metadata": {
    "order_id": "1234",
    "invoice_no": "A123"
  },
  "transactions": [
    {
      "id": "4729294329",
      "currency": "EUR",
      "amount": "123.34",
      "state": "pending"
    }
  ],
  "nearest_stores": [
    {
      "title": "mobilcom-debitel",
      "logo": {
        "id": "17077"
      },
      "distance_m": 1160,
      "address": {
        "city": "Berlin",
        "country": "DE",
        "street_and_no": "Grunerstraße 20",
        "zipcode": "10179"
      },
      "opening_hours": {
        "days": [
          { "day": "sun", "open": [] },
          { "day": "mon", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "tue", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "wed", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "thu", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "fri", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "sat", "open": [{"begin": "10:00", "end": "21:00"}] }
        ]
      }
    },
    {
      "title": "dm-drogerie markt",
      "logo": {
        "id": "13045"
      },
      "distance_m": 1220,
      "address": {
        "city": "Berlin",
        "country": "DE",
        "street_and_no": "Alexanderplatz 1",
        "zipcode": "10178"
      },
      "opening_hours": {
        "days": [
          { "day": "sun", "open": [] },
          { "day": "mon", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "tue", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "wed", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "thu", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "fri", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "sat", "open": [{"begin": "09:00", "end": "22:00"}] }
        ]
      }
    },
    {
      "title": "dm-drogerie markt",
      "logo": {
        "id": "13045"
      },
      "distance_m": 1280,
      "address": {
        "city": "Berlin",
        "country": "DE",
        "street_and_no": "Henriette-Herz-Platz 4",
        "zipcode": "10178"
      },
      "opening_hours": {
        "days": [
          { "day": "sun", "open": [] },
          { "day": "mon", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "tue", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "wed", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "thu", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "fri", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "sat", "open": [{"begin": "09:00", "end": "21:00"}] }
        ]
      }
    }
  ]
}

Response Attributes

Name Type Description Example
barcode_ean13 string This number represents the barcode the customer gives to a cashier in a store. This field is not returned by default. See Optional Fields for more information.
Pattern: ^[0-9]{13}$
Length: 13
"4051234567890"
checkout_token string Token used for displaying the Barzahlen checkout page. The field is only returned in responses to POST /slips requests with a payment slip_type, but not for other endpoints or slip types.
Length: 20..255
"djF8Y2hrdHxzbH..."
customer:​cell_phone_last_4_digits nullable string Last 4 digits of the customer’s cell phone number (cut off for privacy reasons)
Pattern: ^[0-9]*$
Length: 4
"6789"
customer:​email nullable string The customer’s email address.
Length: 3..88
"john@example.com"
customer:​key string A key uniquely identifying the customer. See Identifying a customer for more information.
Pattern: ^[a-zA-Z0-9!"#\$%&'()*+,-\./:;<=>\?@\[\\\]\^_\{\|\}~]+$
Length: 0..40
"LDFKHSLFDHFL"
customer:​language string The language used for communicating with the customer (e.g. for email, text message, web interface) (RFC 5646 language-region code).
One of: "de-DE"
"de-DE"
division_id string A string identifying the division that created the slip. A division can only access their own slips, so this is always the same per API key.
Length: 1..50
"1234"
expires_at date-time Time the slip expires and can no longer be used. Format is date-time as defined in RFC 3339 Section 5.6. "2015-01-01T12:00:00Z"
hook_url nullable string Per-slip webhook URL to use instead of the one configured in Control Center. See Webhooks. null
id string A string identifying a slip.
Length: 1..50
"slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd"
metadata object Custom metadata not processed by Barzahlen, useful for associating slips with internal identifiers. Keys and values are strings.
nearest_stores/​address:​city string The store’s city.
Length: 1..255
"Berlin"
nearest_stores/​address:​country string The store’s country, a ISO 3166-1 alpha 2 language code.
Pattern: ^[A-Z]+$
Length: 0..2
"DE"
nearest_stores/​address:​street_and_no string The store’s street and house number.
Length: 0..255
"Wallstr. 14a"
nearest_stores/​address:​zipcode string The store’s zip code.
Length: 0..10
"10123"
nearest_stores/​distance_m integer Distance in meters from the given address to the store. Note that for refunds, we currently ignore the address given when creating the refund and use the address given when creating the original payment. 42
nearest_stores/​logo:​id string A unique identifier for a logo related to the store. Please contact us if you want to use store logos.
Length: 1..50
"example"
nearest_stores/​opening_hours:​days/​day string The day of week the opening hours are valid for. Note that the JSON objects describing the different weekdays are always ordered, beginning with Sunday. You do not necessarily have to evaluate this field, but can assume that the first object in the 'days’ array refers to Sunday, the second to Monday, and so on.
One of: "sun" or "mon" or "tue" or "wed" or "thu" or "fri" or "sat"
"sun"
nearest_stores/​opening_hours:​days/​open/​begin string Time the store opens. Stores may open multiple times a day, so the 'open’ array can contain multiple elements.
Pattern: ^[0-9]{2}:[0-9]{2}$
"example"
nearest_stores/​opening_hours:​days/​open/​end string Time the store closes.
Pattern: ^[0-9]{2}:[0-9]{2}$
"example"
nearest_stores/​title string The store’s name.
Length: 1..120
"example"
reference_key nullable string A key referencing an order or another internal process.
Pattern: ^[a-zA-Z0-9!"#\$%&'()*+,-\./:;<=>\?@\[\\\]\^_\{\|\}~]+$
Length: 0..40
"O64737X"
refund:​for_slip_id string For refunds, references a payment slip’s id. See 'Refund Slips’ above.
Length: 1..50
"slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd"
slip_type string Slip type, see above.
One of: "payment" or "refund"
"payment"
transactions/​amount string Amount with a dot as decimal separator and maximum of two decimal places. Negative when paying out money.
Pattern: ^-?[0-9]+\.[0-9]+$
"123.34"
transactions/​currency string Currency as three-letter ISO 4217 code.
Length: 3
"EUR"
transactions/​id string A string identifying a transaction. As with all values in this API returned as string, if you need to store this, make sure to store it as a string.
Length: 1..50
"4729294329"
transactions/​state string A transaction’s state. Only pending transactions can be modified.
One of: "pending" or "paid" or "expired" or "invalidated"
"pending"

Download JSON schema

Headers

Header Description
Authorization A per-request signature for authentication, see Authentication.
Idempotency-Key A required random string unique per slip to be created, see Idempotency.

Errors

General API Errors can also be returned by this resource. See also Errors.

Status Class Code and hints
400 idempotency invalid_idempotency_key
400 idempotency reused_idempotency_key - Key reused with different parameters
415 invalid_format request_body_not_valid_json
400 invalid_format unknown_additional_parameter
400 invalid_state associated_slip_not_found - For refunds only, the payment slip could not be found.
400 invalid_state associated_slip_not_a_payment - For refunds only.
400 invalid_state associated_slip_not_paid - For refunds only.
400 invalid_state associated_slip_anonymized - For refunds only, the payment slip has been anonymized.
400 invalid_state reference_key_already_exists - Your division is configured to not allow duplicate reference keys.
400 invalid_parameter customer_cell_phone_not_settable
400 invalid_parameter customer_email_not_settable
400 invalid_parameter customer_key_not_settable
400 invalid_parameter customer_language_not_settable
400 invalid_parameter reference_key_not_settable
400 invalid_parameter invalid_slip_type
400 invalid_parameter invalid_refund
400 invalid_parameter invalid_refund_for_slip_id
400 invalid_parameter invalid_hook_url
400 invalid_parameter invalid_expires_at
400 invalid_parameter invalid_customer
400 invalid_parameter invalid_customer_key
400 invalid_parameter invalid_customer_cell_phone
400 invalid_parameter invalid_customer_email
400 invalid_parameter invalid_customer_language
400 invalid_parameter invalid_metadata
400 invalid_parameter invalid_show_stores_near
400 invalid_parameter invalid_show_stores_near_address_street_and_no
400 invalid_parameter invalid_show_stores_near_address_zipcode
400 invalid_parameter invalid_show_stores_near_address_city
400 invalid_parameter invalid_show_stores_near_address_country
400 invalid_parameter invalid_transactions
400 invalid_parameter invalid_transactions_currency
400 invalid_parameter invalid_transactions_amount
400 invalid_parameter too_early_expires_at
400 invalid_parameter too_late_expires_at
403 not_allowed legal_amount_limit_exceeded - For legal reasons, we are only allowed to process a certain amount per time.
403 not_allowed slip_type_not_allowed - Contact us if you want to use a slip type currently not allowed for your division.
403 not_allowed available_payout_amount_insufficient - Your division’s available amount for refunds / payouts is insufficient.
403 not_allowed associated_payment_amount_exceeded - The sum of refunds would exceed the sum of the associated payment slip.

Retrieve Slip

GET /slips/{id}

Retrieve information about a slip.

Example Response Body for HTTP status 200

{
  "id": "slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd",
  "slip_type": "payment",
  "division_id": "1234",
  "reference_key": "O64737X",
  "hook_url": "https://psp.example.com/hook",
  "expires_at": "2016-01-10T12:34:56Z",
  "customer": {
    "key": "LDFKHSLFDHFL",
    "cell_phone_last_4_digits": "6789",
    "email": "john@example.com",
    "language": "de-DE"
  },
  "metadata": {
    "order_id": "1234",
    "invoice_no": "A123"
  },
  "transactions": [
    {
      "id": "4729294329",
      "currency": "EUR",
      "amount": "123.34",
      "state": "pending"
    }
  ],
  "nearest_stores": [
    {
      "title": "mobilcom-debitel",
      "logo": {
        "id": "17077"
      },
      "distance_m": 1160,
      "address": {
        "city": "Berlin",
        "country": "DE",
        "street_and_no": "Grunerstraße 20",
        "zipcode": "10179"
      },
      "opening_hours": {
        "days": [
          { "day": "sun", "open": [] },
          { "day": "mon", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "tue", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "wed", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "thu", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "fri", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "sat", "open": [{"begin": "10:00", "end": "21:00"}] }
        ]
      }
    },
    {
      "title": "dm-drogerie markt",
      "logo": {
        "id": "13045"
      },
      "distance_m": 1220,
      "address": {
        "city": "Berlin",
        "country": "DE",
        "street_and_no": "Alexanderplatz 1",
        "zipcode": "10178"
      },
      "opening_hours": {
        "days": [
          { "day": "sun", "open": [] },
          { "day": "mon", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "tue", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "wed", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "thu", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "fri", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "sat", "open": [{"begin": "09:00", "end": "22:00"}] }
        ]
      }
    },
    {
      "title": "dm-drogerie markt",
      "logo": {
        "id": "13045"
      },
      "distance_m": 1280,
      "address": {
        "city": "Berlin",
        "country": "DE",
        "street_and_no": "Henriette-Herz-Platz 4",
        "zipcode": "10178"
      },
      "opening_hours": {
        "days": [
          { "day": "sun", "open": [] },
          { "day": "mon", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "tue", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "wed", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "thu", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "fri", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "sat", "open": [{"begin": "09:00", "end": "21:00"}] }
        ]
      }
    }
  ]
}

Response Attributes

Name Type Description Example
barcode_ean13 string This number represents the barcode the customer gives to a cashier in a store. This field is not returned by default. See Optional Fields for more information.
Pattern: ^[0-9]{13}$
Length: 13
"4051234567890"
customer:​cell_phone_last_4_digits nullable string Last 4 digits of the customer’s cell phone number (cut off for privacy reasons)
Pattern: ^[0-9]*$
Length: 4
"6789"
customer:​email nullable string The customer’s email address.
Length: 3..88
"john@example.com"
customer:​key string A key uniquely identifying the customer. See Identifying a customer for more information.
Pattern: ^[a-zA-Z0-9!"#\$%&'()*+,-\./:;<=>\?@\[\\\]\^_\{\|\}~]+$
Length: 0..40
"LDFKHSLFDHFL"
customer:​language string The language used for communicating with the customer (e.g. for email, text message, web interface) (RFC 5646 language-region code).
One of: "de-DE"
"de-DE"
division_id string A string identifying the division that created the slip. A division can only access their own slips, so this is always the same per API key.
Length: 1..50
"1234"
expires_at date-time Time the slip expires and can no longer be used. Format is date-time as defined in RFC 3339 Section 5.6. "2015-01-01T12:00:00Z"
hook_url nullable string Per-slip webhook URL to use instead of the one configured in Control Center. See Webhooks. null
id string A string identifying a slip.
Length: 1..50
"slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd"
metadata object Custom metadata not processed by Barzahlen, useful for associating slips with internal identifiers. Keys and values are strings.
nearest_stores/​address:​city string The store’s city.
Length: 1..255
"Berlin"
nearest_stores/​address:​country string The store’s country, a ISO 3166-1 alpha 2 language code.
Pattern: ^[A-Z]+$
Length: 0..2
"DE"
nearest_stores/​address:​street_and_no string The store’s street and house number.
Length: 0..255
"Wallstr. 14a"
nearest_stores/​address:​zipcode string The store’s zip code.
Length: 0..10
"10123"
nearest_stores/​distance_m integer Distance in meters from the given address to the store. Note that for refunds, we currently ignore the address given when creating the refund and use the address given when creating the original payment. 42
nearest_stores/​logo:​id string A unique identifier for a logo related to the store. Please contact us if you want to use store logos.
Length: 1..50
"example"
nearest_stores/​opening_hours:​days/​day string The day of week the opening hours are valid for. Note that the JSON objects describing the different weekdays are always ordered, beginning with Sunday. You do not necessarily have to evaluate this field, but can assume that the first object in the 'days’ array refers to Sunday, the second to Monday, and so on.
One of: "sun" or "mon" or "tue" or "wed" or "thu" or "fri" or "sat"
"sun"
nearest_stores/​opening_hours:​days/​open/​begin string Time the store opens. Stores may open multiple times a day, so the 'open’ array can contain multiple elements.
Pattern: ^[0-9]{2}:[0-9]{2}$
"example"
nearest_stores/​opening_hours:​days/​open/​end string Time the store closes.
Pattern: ^[0-9]{2}:[0-9]{2}$
"example"
nearest_stores/​title string The store’s name.
Length: 1..120
"example"
reference_key nullable string A key referencing an order or another internal process.
Pattern: ^[a-zA-Z0-9!"#\$%&'()*+,-\./:;<=>\?@\[\\\]\^_\{\|\}~]+$
Length: 0..40
"O64737X"
refund:​for_slip_id string For refunds, references a payment slip’s id. See 'Refund Slips’ above.
Length: 1..50
"slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd"
slip_type string Slip type, see above.
One of: "payment" or "refund"
"payment"
transactions/​amount string Amount with a dot as decimal separator and maximum of two decimal places. Negative when paying out money.
Pattern: ^-?[0-9]+\.[0-9]+$
"123.34"
transactions/​currency string Currency as three-letter ISO 4217 code.
Length: 3
"EUR"
transactions/​id string A string identifying a transaction. As with all values in this API returned as string, if you need to store this, make sure to store it as a string.
Length: 1..50
"4729294329"
transactions/​state string A transaction’s state. Only pending transactions can be modified.
One of: "pending" or "paid" or "expired" or "invalidated"
"pending"

Download JSON schema

Headers

Header Description
Authorization A per-request signature for authentication, see Authentication.

URL Parameters

Parameter Description Format
id A slip’s id. String

Errors

General API Errors can also be returned by this resource. See also Errors.

Status Class Code and hints
404 invalid_state slip_not_found

Update Slip

PATCH /slips/{id}

Change certain slip attributes. Only slips with a pending transaction can be updated. We notify the customer about certain changes.

When one of the following values is changed, we send an email to the customer:

When customer:cell_phone is changed for a payment slip, we send a text message to the new recipient. We don’t send text messages for refund slips.

For payments, the following attributes can be changed:

For refunds, the following attribute can be changed:

None of the fields are required. If a field is provided, the API tries to update it. Do not pass null for fields you do not want to change, that would mean setting the field to null (which is not possible for most fields).

For any field, passing the value that is already set is not treated as a change by the API. E.g. setting the same customer email the slip already has does not result in an additional email being sent.

We generally discourage changing the amount after the user has received an email or text message due to a poor user experience: The amount shown in a user’s PDF slip or text message can differ from the amount shown by the cash register, which might be unexpected for the customer. If you need to update the amount after creating a slip, we recommend creating the slip without email and cell_phone number and setting them later, together with the amount.

Example Request Body

{
  "customer": {
    "email": "john@example.com",
    "cell_phone": "+495423112345"
  },
  "expires_at": "2016-01-10T12:34:56Z",
  "transactions": [
    {
      "id": "4729294329",
      "amount": "150.00"
    }
  ],
  "reference_key": "NEWKEY"
}

Request Attributes

Name Type Description Example
customer:​cell_phone nullable string The customer’s cell phone number in international format. If set to a non-null value, can not be reset to null.
Pattern: ^\+[0-9]+$
Length: 9..19
"+49151123456789"
customer:​email nullable string The customer’s email address. If set to a non-null value, can’t be reset to null.
Length: 3..80
"john@example.com"
expires_at date-time Time the slip expires and can no longer be used. Format is date-time as defined in RFC 3339 Section 5.6.
Pattern: ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(|\.[0-9]+)(Z|[\+-][0-9]{2}:[0-9]{2})$
"2015-01-01T12:00:00Z"
reference_key nullable string A key referencing an order or another internal process. Can only be changed if it wasn’t set previously, so if the previous value is null.
Pattern: ^[a-zA-Z0-9!"#\$%&'()*+,-\./:;<=>\?@\[\\\]\^_\{\|\}~]+$
Length: 0..40
"O64737X"
transactions/​amount string Amount to be paid in/out with a dot as decimal separator and maximum of two decimal places. We discourage changing the amount after the user has received the slip, see above.
Pattern: ^-?[0-9]+\.[0-9]+$
"81.32"
transactions/​id string The id of the transaction to be changed. Note that this is not the slip id. "4729294329"

Download JSON schema

Example Response Body for HTTP status 200

{
  "id": "slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd",
  "slip_type": "payment",
  "division_id": "1234",
  "reference_key": "O64737X",
  "hook_url": "https://psp.example.com/hook",
  "expires_at": "2016-01-10T12:34:56Z",
  "customer": {
    "key": "LDFKHSLFDHFL",
    "cell_phone_last_4_digits": "6789",
    "email": "john@example.com",
    "language": "de-DE"
  },
  "metadata": {
    "order_id": "1234",
    "invoice_no": "A123"
  },
  "transactions": [
    {
      "id": "4729294329",
      "currency": "EUR",
      "amount": "123.34",
      "state": "pending"
    }
  ],
  "nearest_stores": [
    {
      "title": "mobilcom-debitel",
      "logo": {
        "id": "17077"
      },
      "distance_m": 1160,
      "address": {
        "city": "Berlin",
        "country": "DE",
        "street_and_no": "Grunerstraße 20",
        "zipcode": "10179"
      },
      "opening_hours": {
        "days": [
          { "day": "sun", "open": [] },
          { "day": "mon", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "tue", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "wed", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "thu", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "fri", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "sat", "open": [{"begin": "10:00", "end": "21:00"}] }
        ]
      }
    },
    {
      "title": "dm-drogerie markt",
      "logo": {
        "id": "13045"
      },
      "distance_m": 1220,
      "address": {
        "city": "Berlin",
        "country": "DE",
        "street_and_no": "Alexanderplatz 1",
        "zipcode": "10178"
      },
      "opening_hours": {
        "days": [
          { "day": "sun", "open": [] },
          { "day": "mon", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "tue", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "wed", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "thu", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "fri", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "sat", "open": [{"begin": "09:00", "end": "22:00"}] }
        ]
      }
    },
    {
      "title": "dm-drogerie markt",
      "logo": {
        "id": "13045"
      },
      "distance_m": 1280,
      "address": {
        "city": "Berlin",
        "country": "DE",
        "street_and_no": "Henriette-Herz-Platz 4",
        "zipcode": "10178"
      },
      "opening_hours": {
        "days": [
          { "day": "sun", "open": [] },
          { "day": "mon", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "tue", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "wed", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "thu", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "fri", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "sat", "open": [{"begin": "09:00", "end": "21:00"}] }
        ]
      }
    }
  ]
}

Response Attributes

Name Type Description Example
barcode_ean13 string This number represents the barcode the customer gives to a cashier in a store. This field is not returned by default. See Optional Fields for more information.
Pattern: ^[0-9]{13}$
Length: 13
"4051234567890"
customer:​cell_phone_last_4_digits nullable string Last 4 digits of the customer’s cell phone number (cut off for privacy reasons)
Pattern: ^[0-9]*$
Length: 4
"6789"
customer:​email nullable string The customer’s email address.
Length: 3..88
"john@example.com"
customer:​key string A key uniquely identifying the customer. See Identifying a customer for more information.
Pattern: ^[a-zA-Z0-9!"#\$%&'()*+,-\./:;<=>\?@\[\\\]\^_\{\|\}~]+$
Length: 0..40
"LDFKHSLFDHFL"
customer:​language string The language used for communicating with the customer (e.g. for email, text message, web interface) (RFC 5646 language-region code).
One of: "de-DE"
"de-DE"
division_id string A string identifying the division that created the slip. A division can only access their own slips, so this is always the same per API key.
Length: 1..50
"1234"
expires_at date-time Time the slip expires and can no longer be used. Format is date-time as defined in RFC 3339 Section 5.6. "2015-01-01T12:00:00Z"
hook_url nullable string Per-slip webhook URL to use instead of the one configured in Control Center. See Webhooks. null
id string A string identifying a slip.
Length: 1..50
"slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd"
metadata object Custom metadata not processed by Barzahlen, useful for associating slips with internal identifiers. Keys and values are strings.
nearest_stores/​address:​city string The store’s city.
Length: 1..255
"Berlin"
nearest_stores/​address:​country string The store’s country, a ISO 3166-1 alpha 2 language code.
Pattern: ^[A-Z]+$
Length: 0..2
"DE"
nearest_stores/​address:​street_and_no string The store’s street and house number.
Length: 0..255
"Wallstr. 14a"
nearest_stores/​address:​zipcode string The store’s zip code.
Length: 0..10
"10123"
nearest_stores/​distance_m integer Distance in meters from the given address to the store. Note that for refunds, we currently ignore the address given when creating the refund and use the address given when creating the original payment. 42
nearest_stores/​logo:​id string A unique identifier for a logo related to the store. Please contact us if you want to use store logos.
Length: 1..50
"example"
nearest_stores/​opening_hours:​days/​day string The day of week the opening hours are valid for. Note that the JSON objects describing the different weekdays are always ordered, beginning with Sunday. You do not necessarily have to evaluate this field, but can assume that the first object in the 'days’ array refers to Sunday, the second to Monday, and so on.
One of: "sun" or "mon" or "tue" or "wed" or "thu" or "fri" or "sat"
"sun"
nearest_stores/​opening_hours:​days/​open/​begin string Time the store opens. Stores may open multiple times a day, so the 'open’ array can contain multiple elements.
Pattern: ^[0-9]{2}:[0-9]{2}$
"example"
nearest_stores/​opening_hours:​days/​open/​end string Time the store closes.
Pattern: ^[0-9]{2}:[0-9]{2}$
"example"
nearest_stores/​title string The store’s name.
Length: 1..120
"example"
reference_key nullable string A key referencing an order or another internal process.
Pattern: ^[a-zA-Z0-9!"#\$%&'()*+,-\./:;<=>\?@\[\\\]\^_\{\|\}~]+$
Length: 0..40
"O64737X"
refund:​for_slip_id string For refunds, references a payment slip’s id. See 'Refund Slips’ above.
Length: 1..50
"slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd"
slip_type string Slip type, see above.
One of: "payment" or "refund"
"payment"
transactions/​amount string Amount with a dot as decimal separator and maximum of two decimal places. Negative when paying out money.
Pattern: ^-?[0-9]+\.[0-9]+$
"123.34"
transactions/​currency string Currency as three-letter ISO 4217 code.
Length: 3
"EUR"
transactions/​id string A string identifying a transaction. As with all values in this API returned as string, if you need to store this, make sure to store it as a string.
Length: 1..50
"4729294329"
transactions/​state string A transaction’s state. Only pending transactions can be modified.
One of: "pending" or "paid" or "expired" or "invalidated"
"pending"

Download JSON schema

Headers

Header Description
Authorization A per-request signature for authentication, see Authentication.

URL Parameters

Parameter Description Format
id A slip’s id. String

Errors

General API Errors can also be returned by this resource. See also Errors.

Status Class Code and hints
415 invalid_format request_body_not_valid_json
400 invalid_format unknown_additional_parameter
404 invalid_state slip_not_found
400 invalid_state slip_invalidated
400 invalid_state slip_expired
400 invalid_state slip_locked - Slip has been scanned in a store and not yet been paid.
400 invalid_state slip_paid
400 invalid_state customer_cell_phone_cannot_be_removed - A previously set customer phone number cannot be removed, only changed.
400 invalid_state customer_email_cannot_be_removed - A previously set customer email cannot be removed, only changed.
400 invalid_state reference_key_already_set - The slip already has a reference key set.
400 invalid_state reference_key_already_exists - Your division is configured to not allow duplicate reference keys.
400 invalid_state transaction_not_found
400 invalid_parameter customer_cell_phone_not_settable
400 invalid_parameter customer_email_not_settable
400 invalid_parameter reference_key_not_settable
400 invalid_parameter transactions_amount_not_settable
400 invalid_parameter invalid_expires_at
400 invalid_parameter invalid_customer
400 invalid_parameter invalid_customer_cell_phone
400 invalid_parameter invalid_customer_email
400 invalid_parameter invalid_reference_key
400 invalid_parameter invalid_transactions
400 invalid_parameter invalid_transactions_id
400 invalid_parameter invalid_transactions_amount
400 invalid_parameter too_early_expires_at
400 invalid_parameter too_late_expires_at
403 not_allowed legal_amount_limit_exceeded - For legal reasons, we are only allowed to process a certain amount per time.
403 not_allowed slip_text_message_resend_limit_exceeded

Resend Email / Text Message

POST /slips/{id}/resend/{message_type}

Resend the email or text message containing slip information like the barcode to the customer. Only possible for slips with a pending transaction. Text messages can only be sent for payment slips and not for refund slips.

Text messages can only be resent twice. After that, an attempt to resend a text message will return an error. Resending a text message by changing the customer:cell_phone number via PATCH also counts as a resend and is no longer possible when the limit has been reached.

Note that the sandbox API endpoint does not send text messages.

This endpoint returns an empty JSON object as response.

Example Response Body for HTTP status 202

{}

Headers

Header Description
Authorization A per-request signature for authentication, see Authentication.

URL Parameters

Parameter Description Format
id A slip’s id. String
message_type String, one of (email,text_message)

Errors

General API Errors can also be returned by this resource. See also Errors.

Status Class Code and hints
404 invalid_state slip_not_found
400 invalid_state slip_invalidated
400 invalid_state slip_expired
400 invalid_state slip_paid
400 invalid_state slip_does_not_have_customer_cell_phone
400 invalid_state slip_does_not_have_customer_email
403 not_allowed slip_text_message_resend_limit_exceeded

Invalidate Slip

POST /slips/{id}/invalidate

Invalidate a slip so it can no longer be used. Only possible for slips with a pending transaction, so e.g. paid slips can not be invalidated.

This action is final and can not be undone. An invalid slip can no longer be updated or resent via the API or paid by the customer.

When the slip contains a customer:email, we notify the customer via email that the slip is no longer valid.

Invalidating an already invalidated slip does nothing and returns the slip as if it had not been invalidated before.

Example Response Body for HTTP status 200

{
  "id": "slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd",
  "slip_type": "payment",
  "division_id": "1234",
  "reference_key": "O64737X",
  "hook_url": "https://psp.example.com/hook",
  "expires_at": "2016-01-10T12:34:56Z",
  "customer": {
    "key": "LDFKHSLFDHFL",
    "cell_phone_last_4_digits": "6789",
    "email": "john@example.com",
    "language": "de-DE"
  },
  "metadata": {
    "order_id": "1234",
    "invoice_no": "A123"
  },
  "transactions": [
    {
      "id": "4729294329",
      "currency": "EUR",
      "amount": "123.34",
      "state": "pending"
    }
  ],
  "nearest_stores": [
    {
      "title": "mobilcom-debitel",
      "logo": {
        "id": "17077"
      },
      "distance_m": 1160,
      "address": {
        "city": "Berlin",
        "country": "DE",
        "street_and_no": "Grunerstraße 20",
        "zipcode": "10179"
      },
      "opening_hours": {
        "days": [
          { "day": "sun", "open": [] },
          { "day": "mon", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "tue", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "wed", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "thu", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "fri", "open": [{"begin": "10:00", "end": "21:00"}] },
          { "day": "sat", "open": [{"begin": "10:00", "end": "21:00"}] }
        ]
      }
    },
    {
      "title": "dm-drogerie markt",
      "logo": {
        "id": "13045"
      },
      "distance_m": 1220,
      "address": {
        "city": "Berlin",
        "country": "DE",
        "street_and_no": "Alexanderplatz 1",
        "zipcode": "10178"
      },
      "opening_hours": {
        "days": [
          { "day": "sun", "open": [] },
          { "day": "mon", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "tue", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "wed", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "thu", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "fri", "open": [{"begin": "09:00", "end": "22:00"}] },
          { "day": "sat", "open": [{"begin": "09:00", "end": "22:00"}] }
        ]
      }
    },
    {
      "title": "dm-drogerie markt",
      "logo": {
        "id": "13045"
      },
      "distance_m": 1280,
      "address": {
        "city": "Berlin",
        "country": "DE",
        "street_and_no": "Henriette-Herz-Platz 4",
        "zipcode": "10178"
      },
      "opening_hours": {
        "days": [
          { "day": "sun", "open": [] },
          { "day": "mon", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "tue", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "wed", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "thu", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "fri", "open": [{"begin": "08:30", "end": "21:00"}] },
          { "day": "sat", "open": [{"begin": "09:00", "end": "21:00"}] }
        ]
      }
    }
  ]
}

Response Attributes

Name Type Description Example
barcode_ean13 string This number represents the barcode the customer gives to a cashier in a store. This field is not returned by default. See Optional Fields for more information.
Pattern: ^[0-9]{13}$
Length: 13
"4051234567890"
customer:​cell_phone_last_4_digits nullable string Last 4 digits of the customer’s cell phone number (cut off for privacy reasons)
Pattern: ^[0-9]*$
Length: 4
"6789"
customer:​email nullable string The customer’s email address.
Length: 3..88
"john@example.com"
customer:​key string A key uniquely identifying the customer. See Identifying a customer for more information.
Pattern: ^[a-zA-Z0-9!"#\$%&'()*+,-\./:;<=>\?@\[\\\]\^_\{\|\}~]+$
Length: 0..40
"LDFKHSLFDHFL"
customer:​language string The language used for communicating with the customer (e.g. for email, text message, web interface) (RFC 5646 language-region code).
One of: "de-DE"
"de-DE"
division_id string A string identifying the division that created the slip. A division can only access their own slips, so this is always the same per API key.
Length: 1..50
"1234"
expires_at date-time Time the slip expires and can no longer be used. Format is date-time as defined in RFC 3339 Section 5.6. "2015-01-01T12:00:00Z"
hook_url nullable string Per-slip webhook URL to use instead of the one configured in Control Center. See Webhooks. null
id string A string identifying a slip.
Length: 1..50
"slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd"
metadata object Custom metadata not processed by Barzahlen, useful for associating slips with internal identifiers. Keys and values are strings.
nearest_stores/​address:​city string The store’s city.
Length: 1..255
"Berlin"
nearest_stores/​address:​country string The store’s country, a ISO 3166-1 alpha 2 language code.
Pattern: ^[A-Z]+$
Length: 0..2
"DE"
nearest_stores/​address:​street_and_no string The store’s street and house number.
Length: 0..255
"Wallstr. 14a"
nearest_stores/​address:​zipcode string The store’s zip code.
Length: 0..10
"10123"
nearest_stores/​distance_m integer Distance in meters from the given address to the store. Note that for refunds, we currently ignore the address given when creating the refund and use the address given when creating the original payment. 42
nearest_stores/​logo:​id string A unique identifier for a logo related to the store. Please contact us if you want to use store logos.
Length: 1..50
"example"
nearest_stores/​opening_hours:​days/​day string The day of week the opening hours are valid for. Note that the JSON objects describing the different weekdays are always ordered, beginning with Sunday. You do not necessarily have to evaluate this field, but can assume that the first object in the 'days’ array refers to Sunday, the second to Monday, and so on.
One of: "sun" or "mon" or "tue" or "wed" or "thu" or "fri" or "sat"
"sun"
nearest_stores/​opening_hours:​days/​open/​begin string Time the store opens. Stores may open multiple times a day, so the 'open’ array can contain multiple elements.
Pattern: ^[0-9]{2}:[0-9]{2}$
"example"
nearest_stores/​opening_hours:​days/​open/​end string Time the store closes.
Pattern: ^[0-9]{2}:[0-9]{2}$
"example"
nearest_stores/​title string The store’s name.
Length: 1..120
"example"
reference_key nullable string A key referencing an order or another internal process.
Pattern: ^[a-zA-Z0-9!"#\$%&'()*+,-\./:;<=>\?@\[\\\]\^_\{\|\}~]+$
Length: 0..40
"O64737X"
refund:​for_slip_id string For refunds, references a payment slip’s id. See 'Refund Slips’ above.
Length: 1..50
"slp-d90ab05c-69f2-4e87-9972-97b3275a0ccd"
slip_type string Slip type, see above.
One of: "payment" or "refund"
"payment"
transactions/​amount string Amount with a dot as decimal separator and maximum of two decimal places. Negative when paying out money.
Pattern: ^-?[0-9]+\.[0-9]+$
"123.34"
transactions/​currency string Currency as three-letter ISO 4217 code.
Length: 3
"EUR"
transactions/​id string A string identifying a transaction. As with all values in this API returned as string, if you need to store this, make sure to store it as a string.
Length: 1..50
"4729294329"
transactions/​state string A transaction’s state. Only pending transactions can be modified.
One of: "pending" or "paid" or "expired" or "invalidated"
"pending"

Download JSON schema

Headers

Header Description
Authorization A per-request signature for authentication, see Authentication.

URL Parameters

Parameter Description Format
id A slip’s id. String

Errors

General API Errors can also be returned by this resource. See also Errors.

Status Class Code and hints
404 invalid_state slip_not_found
400 invalid_state slip_expired
400 invalid_state slip_locked - Slip has been scanned in a store and not yet been paid.
400 invalid_state slip_paid