Introduction
viafintech API Stores v3 provides three endpoints. Two endpoints are for retrieving stores which offer the Barzahlen/viacash service including their opening hours and coordinates.
It is possible to find stores:
- located close to a given point.
- located within a rectangular bounding box of geocoordinates.
The two endpoints offer different use cases, for example:
- The
/nearby
endpoint could be used to find the closest stores to a specific location. - The
/within_bounds
endpoint can be used to show the stores on a map without a specific single reference point.
The third endpoint is for providing feedback about the experience at a specific store.
The goal of this API is to allow building user interfaces which make it convenient for customers to find stores offering Barzahlen/viacash.
The API is a JSON-based REST API.
Functionality
- /stores/nearby Find the nearest 10 stores from a given point (lat,lng).
- /stores/within_bounds Find stores that lie within the created bounding box from two given points (top left, bottom right).
- /stores/{id}/feedbacks Provide feedback about the specific store by its
id
value.
Accessing the API
The API is accessible via HTTPS and uses JSON as the format for requests and responses. As a REST-API, it uses the appropriate 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 base API endpoint is: https://stores.viafintech.com/v3
HTTPS/TLS Protocols and Certificates
We employ TLS protocols to ensure secure communications between our systems and our partners' systems. Our systems currently supports both TLS 1.2 and TLS 1.3, using a range of secure encryption ciphers. We expect our partners to implement support for these protocols in their systems as well, to guarantee secure data transmission.
Additionally, we require our partners to maintain an up-to-date list of trusted root certificates (CA Root certificates). This ensures that new HTTPS/TLS connections can be properly verified and trusted, mitigating the risk of man-in-the-middle attacks. We strongly recommend always verifying HTTPS server certificates against trusted root certificates. This includes validating the certificate chain and verifying the server name(s) against the certificate. Refer to your HTTP client’s documentation for details on performing these and other required checks.
To facilitate secure integration, we provide a curated bundle of root certificates (download below) from reputable Certificate Authorities (CAs) that we currently or may in the future use for obtaining certificates for this API. Feel free to integrate this list into your systems to establish secure and reliable connections to our API services or you can also rely on your already existing system trust store. By using either this tailored certificate bundle or your system trust store, you can ensure a seamless and secure experience while making the renewal of our certificates effortless on your end.
- viafintech CA Bundle 2024-12 (combined PEM)
- viafintech CA Bundle 2024-12 (ZIP / contains individual PEM files)
Authentication
For authentication, the API requires each request to include an Authorization header with Basic Auth.
API Requests
Authorization
header format for API requests
Authorization: Basic APIToken
For requests, the API expects a standard HTTP Authorization header.
The Authorization header will need to include the Basic flag and an APIToken.
The APIToken is constructed by two required parts, the Division ID and the API Key for this API.
These parts need to concatenated with a colon :
in the following fashion DivisionID:APIKey
and then base64 encoded.
The Authorization credentials (Division ID and Stores API Key) are accessible via the viafintech App under Settings / Divisions.
Please, use the Stores API Key and be aware that the API Key is only valid for viafintech API v2!
When the Authorization header is missing or invalid, the API returns HTTP status 401 and an error.
Example Request with
Authorization
header
GET /v3/stores/nearby?lat=52.48675300749431&lng=13.35877465576175 HTTP/1.1
Authorization: Basic MTIzNDU6NmQ4ZjMxYzBiYWJiNTA2MGViYTBjZTQxNTZmYmIyNWVkODUzOGU5MQ==
Idempotency
Most methods on resources in viafintech API Stores v3 can 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:
GET /stores/nearby
: Is a read-only request without side-effects, so no need for idempotency.GET /stores/within_bounds
: Is a read-only request without side-effects, so no need for idempotency.POST /stores/{id}/feedbacks
: Allows setting anIdempotency-Key
header. When retrying the same request with the same key, the request will be ignored by the API. Never reuse an idempotency key, we recommand using a randomly generated string, e.g. a UUID v4.
Using the Idempotency-Key
header in any endpoint other than POST /stores/{id}/feedbacks
has no effect and will be ignored.
Rate Limiting
Request Limit
The API is rate limited per API Key to ensure that server resources are not overloaded.
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 Mar 2017 10:54:54 GMT
Ratelimit-Limit: 31
Ratelimit-Remaining: 30
Ratelimit-Reset-After: 1
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. If the bucket has a size of 31, 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. The specific limits may differ depending on the division.
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:
Ratelimit-Limit
: Total number of requests generally allowed at onceRatelimit-Remaining
: Number of requests remainingRatelimit-Reset-After
: Duration in seconds until the limit will be reset to the maximum if no additional requests are executed.Retry-After
: Returned only withrate_limit_exceeded
errors and contains the duration in seconds until the next request is allowed.
Errors
Example Error Response
{
"error_class": "invalid_parameters",
"error_code": "invalid_point_parameters",
"message": "The following parameters have an invalid format: lat, lng"
}
viafintech API Stores v3 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.
Error Classes
auth
: Authentication or authorization problem. Do not automatically retry the same request.idempotency
: A problem concerning the idempotency mechanism. Do not automatically retry the same request.rate_limit
: Too many requests were sent per duration, retry the same request later (see Rate Limiting).invalid_format
: The request body has an invalid format. Do not automatically retry the same request.invalid_parameters
: One of the given parameters does not have the necessary format or is invalid for some other reason. Do not automatically retry the same request.missing_parameters
: One or more required parameters are not present in the request. Do not automatically retry the same request.server_error
: An internal error occurred on our systems. Automatically retry the same request with a limited number of attempts. If the error persists for several hours, please contact us.
General Errors
The message returned with an error code can contain additional information.
Status | Class | Code and hints |
---|---|---|
401 | auth |
invalid_auth |
404 | invalid_format |
invalid_request_url |
429 | rate_limit |
rate_limit_exceeded |
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.
API Stability
We will make backwards-compatible changes to API Stores V3 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:
- Adding new resources.
- Adding new optional request body or query parameters.
- Adding new parameters to response bodies.
- Changing the length or format of id or token parameters. Always store parameters we return as string as such, even if they only contain numbers.
- Adding new error codes. We will not add new error classes, but your code must be able to handle an unknown error code for any error class.
- Changing error messages. Never write code parsing them or using them for anything else than showing them to people, see Errors.
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:
- Removing resources.
- Removing properties from response bodies.
- Changing required query parameters.
- Changing name and type of query parameters.
Changelog
2024-03-20
- Accept
Idempotency-Key
header in the feedback endpoint.
2024-02-07
- Accept
transaction_id
in the feedback endpoint.
2023-10-30
- Added support for sending feedback about stores through the API.
Changes from API v2
- New Version v3.
- Required Authorization header on each API request.
- Endpoint path change -
/stores
is now/stores/within_bounds
. - Endpoint request parameters added:
/stores/within_bounds
now requires four query parameters that form a bounding box instead of a single map bounds string. - The stores will now be filtered automatically by the allowed offline partners for the Division.
- Rate Limiting added to all endpoints.
- Error responses now include a class, code and a message.
/stores/nearby
GET /stores/nearby
Nearby returns a list of the 10 nearest stores to the given point
Example Response Body for HTTP status 200 with Content-Type
application/json
[
{
"id":8321,
"lat":"49.30303",
"lng":"6.80063",
"title":"REWE",
"street_and_no":"Zur Langenlaenge 2",
"zipcode":"66773",
"city":"Schwalbach",
"countrycode":"DE",
"distance":"2.49",
"phone":null,
"parking":null,
"opening_hours_per_day":[
{ "day": "mon", "open": [{ "begin": "08:00", "end": "20:00" }] },
{ "day": "tue", "open": [{ "begin": "08:00", "end": "20:00" }] },
{ "day": "wed", "open": [{ "begin": "08:00", "end": "20:00" }] },
{ "day": "thu", "open": [{ "begin": "08:00", "end": "20:00" }] },
{ "day": "fri", "open": [{ "begin": "08:00", "end": "20:00" }] },
{ "day": "sat", "open": [{ "begin": "08:00", "end": "20:00" }] }
],
"logo_url":"https://cdn.viafintech.com/images/filialfinder/logo_rewe.png",
"logo_thumbnail_url":"https://cdn.viafintech.com/images/filialfinder/tn_rewe.png",
"offline_partner_id":37684,
"minutes_until_close":425,
"transfer_directions": ["in", "out"]
},
{
"id":861,
"lat":"49.3024702",
"lng":"6.8004216",
"title":"dm-drogerie markt",
"street_and_no":"Zur Langelänge 12",
"zipcode":"66773",
"city":"Schwalbach",
"countrycode":"DE",
"distance":"2.53",
"phone":"068345790092",
"parking":true,
"opening_hours_per_day":[
{ "day": "mon", "open": [{ "begin": "08:00", "end": "20:00" }] },
{ "day": "tue", "open": [{ "begin": "08:00", "end": "20:00" }] },
{ "day": "wed", "open": [{ "begin": "08:00", "end": "20:00" }] },
{ "day": "thu", "open": [{ "begin": "08:00", "end": "20:00" }] },
{ "day": "fri", "open": [{ "begin": "08:00", "end": "20:00" }] },
{ "day": "sat", "open": [{ "begin": "08:00", "end": "20:00" }] }
],
"logo_url":"https://cdn.viafintech.com/images/filialfinder/logo_dm-drogerie-markt.png",
"logo_thumbnail_url":"https://cdn.viafintech.com/images/filialfinder/tn_dm-drogerie-markt.png",
"offline_partner_id":13045,
"minutes_until_close":425,
"transfer_directions": ["in"]
}
]
Response Attributes
Name | Type | Description | Example |
---|---|---|---|
city | string | The city in which the store is located. | "Berlin" |
countrycode | string | The country in which the store is located as an ISO 3166-1 alpha 2 language code. | "Berlin" |
distance | string | The distance of the store to the given coordinates in kilometers as a decimal number | "0.53" |
id | integer | A unique identifier of the store | 8321 |
lat | string | The store's latitude represented as a string (between -90.0 and 90.0). This field is not returned by default. See Optional Features for more information. Pattern: ^-?[0-9]+\.[0-9]+$ |
"52.4867530074" |
lng | string | The store's longitude represented as a string (between -180.0 and 180.0). This field is not returned by default. See Optional Features for more information. Pattern: ^-?[0-9]+\.[0-9]+$ |
"13.3587746557" |
logo_thumbnail_url | string | A thumbnail logo for the store to display in a UI. | "https://cdn.viafintech.com/images/filialfinder/tn_viacash.png" |
logo_url | string | A logo for the store to display in a UI. | "https://cdn.viafintech.com/images/filialfinder/logo_viacash.png" |
minutes_until_close | integer | Number of minutes until the store closes. When the value 0 is returned the store is closed at the moment. When the value -1 is returned no opening hour information are available. |
10 |
offline_partner_id | integer | A unique identifier of the partner operating the store. | 12345 |
opening_hours_per_day/day | string | The letter abbreviation for the day of the week. One of: "sun" or "mon" or "tue" or "wed" or "thu" or "fri" or "sat" |
"mon" |
opening_hours_per_day/open/begin | string | The time at which the open block begins. The time is provided in 24h notation. Pattern: ^\d{2}:\d{2}$ |
"08:00" |
opening_hours_per_day/open/end | string | The time at which the open block ends. The time is provided in 24h notation. Pattern: ^\d{2}:\d{2}$ |
"20:00" |
parking | nullable boolean | The parking flag defines whether car parking spots are available. A null value represents that no data is available. | "+49123456789" |
phone | nullable string | The phone number of the specific store. A null value represents that no data is available. | "+49123456789" |
street_and_no | string | The street and house number in which the store is located. | "Budapester Str. 50" |
title | string | The title describing the store, e.g. the brand name of the store. | "viacash store" |
transfer_directions | array | Transfer directions which are supported by the store | "['in','out']" |
zipcode | string | The zipcode in which the store is located. | "10787" |
Headers
Header | Description |
---|---|
Authorization | A per-request Basic Auth Authorization header, see Authentication. |
Query Parameters
Parameter | Description | Mandatory | Format | Default | Example |
---|---|---|---|---|---|
lat | String representation of the point's latitude (between -90.0 and 90.0) | Yes | String | 52.48675300749431 | |
lng | String representation of the point's longitude (between -180.0 and 180.0) | Yes | String | 13.35877465576175 | |
transfer_directions | Defines which transfer_directions to look for when fetching stores | No | String, one of (in,out) | in,out |
Errors
General API Errors can also be returned by this resource. See also Errors.
Status | Class | Code and hints |
---|---|---|
400 | invalid_parameters |
invalid_point_parameters |
400 | missing_parameters |
missing_point_parameters |
/stores/within_bounds
GET /stores/within_bounds
Within Bounds returns a list of stores contained within the formed bounding box of 2 points (top_left, bottom_right)
Example Response Body for HTTP status 200 with Content-Type
application/json
[
{
"id":9818,
"lat":"52.520001",
"lng":"13.3908251",
"title":"ADAMS",
"street_and_no":"Georgenstr. 12",
"zipcode":"10117",
"city":"Berlin",
"countrycode":"DE",
"opening_hours_per_day":[
{ "day": "mon", "open": [{ "begin": "05:00", "end": "22:00" }] },
{ "day": "tue", "open": [{ "begin": "05:00", "end": "22:00" }] },
{ "day": "wed", "open": [{ "begin": "05:00", "end": "22:00" }] },
{ "day": "thu", "open": [{ "begin": "05:00", "end": "22:00" }] },
{ "day": "fri", "open": [{ "begin": "05:00", "end": "23:59" }] },
{ "day": "sat", "open": [{ "begin": "07:00", "end": "23:59" }] },
{ "day": "sun", "open": [{ "begin": "07:00", "end": "22:00" }] }
],
"phone":"03020058992",
"parking":null,
"logo_url":"https://cdn.viafintech.com/images/filialfinder/logo_adams.png",
"logo_thumbnail_url":"https://cdn.viafintech.com/images/filialfinder/tn_adams.png",
"offline_partner_id":34154,
"minutes_until_close":541,
"transfer_directions": ["in", "out"]
},
{
"id":10332,
"lat":"52.51191",
"lng":"13.4818",
"title":"REWE",
"street_and_no":"Frankfurter Allee 144",
"zipcode":"10365",
"city":"Berlin",
"countrycode":"DE",
"opening_hours_per_day":[
{ "day": "mon", "open": [{ "begin": "07:00", "end": "23:59" }] },
{ "day": "tue", "open": [{ "begin": "07:00", "end": "23:59" }] },
{ "day": "wed", "open": [{ "begin": "07:00", "end": "23:59" }] },
{ "day": "thu", "open": [{ "begin": "07:00", "end": "23:59" }] },
{ "day": "fri", "open": [{ "begin": "07:00", "end": "23:59" }] },
{ "day": "sat", "open": [{ "begin": "07:00", "end": "23:30" }] }
],
"phone":null,
"parking":null,
"logo_url":"https://cdn.viafintech.com/images/filialfinder/logo_rewe.png",
"logo_thumbnail_url":"https://cdn.viafintech.com/images/filialfinder/tn_rewe.png",
"offline_partner_id":37684,
"minutes_until_close":660,
"transfer_directions": ["in"]
}
]
Response Attributes
Name | Type | Description | Example |
---|---|---|---|
city | string | The city in which the store is located. | "Berlin" |
countrycode | string | The country in which the store is located as an ISO 3166-1 alpha 2 language code. | "Berlin" |
id | integer | A unique identifier of the store | 8321 |
lat | string | The store's latitude represented as a string (between -90.0 and 90.0). This field is not returned by default. See Optional Features for more information. Pattern: ^-?[0-9]+\.[0-9]+$ |
"52.4867530074" |
lng | string | The store's longitude represented as a string (between -180.0 and 180.0). This field is not returned by default. See Optional Features for more information. Pattern: ^-?[0-9]+\.[0-9]+$ |
"13.3587746557" |
logo_thumbnail_url | string | A thumbnail logo for the store to display in a UI. | "https://cdn.viafintech.com/images/filialfinder/tn_viacash.png" |
logo_url | string | A logo for the store to display in a UI. | "https://cdn.viafintech.com/images/filialfinder/logo_viacash.png" |
minutes_until_close | integer | Number of minutes until the store closes. When the value 0 is returned the store is closed at the moment. When the value -1 is returned no opening hour information are available. |
10 |
offline_partner_id | integer | A unique identifier of the partner operating the store. | 12345 |
opening_hours_per_day/day | string | The letter abbreviation for the day of the week. One of: "sun" or "mon" or "tue" or "wed" or "thu" or "fri" or "sat" |
"mon" |
opening_hours_per_day/open/begin | string | The time at which the open block begins. The time is provided in 24h notation. Pattern: ^\d{2}:\d{2}$ |
"08:00" |
opening_hours_per_day/open/end | string | The time at which the open block ends. The time is provided in 24h notation. Pattern: ^\d{2}:\d{2}$ |
"20:00" |
parking | nullable boolean | The parking flag defines whether car parking spots are available. A null value represents that no data is available. | "+49123456789" |
phone | nullable string | The phone number of the specific store. A null value represents that no data is available. | "+49123456789" |
street_and_no | string | The street and house number in which the store is located. | "Budapester Str. 50" |
title | string | The title describing the store, e.g. the brand name of the store. | "viacash store" |
transfer_directions | array | Transfer directions which are supported by the store | "['in','out']" |
zipcode | string | The zipcode in which the store is located. | "10787" |
Headers
Header | Description |
---|---|
Authorization | A per-request Basic Auth Authorization header, see Authentication. |
Query Parameters
Parameter | Description | Mandatory | Format | Default | Example |
---|---|---|---|---|---|
top_left_lat | String representation of the top left point's latitude (between -90.0 and 90.0) | Yes | String | 51.3053922724 | |
top_left_lng | String representation of the top left point's longitude (between -180.0 and 180.0) | Yes | String | 12.4277257919 | |
bottom_right_lat | String representation of the bottom right point's latitude (between -90.0 and 90.0) | Yes | String | 51.3040373701 | |
bottom_right_lng | String representation of the bottom right point's longitude (between -180.0 and 180.0) | Yes | String | 12.43060112 | |
transfer_directions | Defines which transfer_directions to look for when fetching stores | No | String, one of (in,out) | in,out |
Errors
General API Errors can also be returned by this resource. See also Errors.
Status | Class | Code and hints |
---|---|---|
400 | invalid_parameters |
invalid_bounds_parameters |
400 | invalid_parameters |
bounds_exceeded - The formed bounding box is too big (max is 100 km) |
400 | missing_parameters |
missing_bounds_parameters |
/stores/{id}/feedbacks
POST /stores/{id}/feedbacks
Example Minimal Request Body for providing feedback
{
"category": "store_not_found"
}
Provide feedback for the experience at a given store with its basic category.
It is also possible to provide remarks
for the feedback to give more detailed information about experience with the store.
It is additionally possible and encouraged to provide a transaction_id
for the request to allow addressing feedback with greater details.
This endpoint is not enabled by default. If you want to use this endpoint for any of your divisions, please contact us.
Note: The Idempotency-Key
header is recommended to be passed for this endpoint. See below.
Example Request Body
{
"category": "store_not_found",
"remarks": "The store was not where it was shown on the map but 500m down the street.",
"language": "en-UK",
"transaction_id": "4729294329"
}
Request Attributes
Name | Type | Description | Example |
---|---|---|---|
category | string | The category provides a general definition of the type of experience encountered at the store. One of: "incorrect_opening_hours" or "store_not_found" or "untrained_staff" or "service_no_longer_offered" or "cross_selling_required" or "technical_error" or "other" |
"incorrect_opening_hours" |
language | nullable string | The language used for communicating with the customer, e.g. in the user interface (RFC 5646 language-region code). Pattern: ^[a-z]{2}-[A-Z]{2}$ |
"de-DE" |
remarks | nullable string | Providing remarks allows for a clearer free text description of the experience encountered to give more nuance and details. Length: 0..1000 |
null |
transaction_id | nullable string | The transaction ID is a unique identifier and if given, must match a value returned for the division during slip creation in the transactions/id response field. It can be used to associate the feedback to a specific transaction and improve the possibility to follow up on any issues. Length: 1..50 |
"4729294329" |
Example Response Body for HTTP status 200 with Content-Type
application/json
{}
Headers
Header | Description |
---|---|
Authorization | A per-request Basic Auth Authorization header, see Authentication. |
Idempotency-Key | An optional random string unique per feedback to be sent, see Idempotency. |
URL Parameters
Parameter | Description | Format |
---|---|---|
id | Store id | Integer |
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 |
400 | invalid_format |
invalid_id |
400 | invalid_format |
invalid_query_params |
400 | invalid_format |
request_body_not_valid_json |
400 | invalid_parameter |
invalid_category |
400 | invalid_parameter |
invalid_remarks |
400 | invalid_parameter |
invalid_language |
400 | invalid_parameter |
invalid_transaction_id |
403 | not_allowed |
store_feedback_not_allowed |
404 | invalid_state |
store_not_found |
400 | missing_parameters |
missing_bounds_parameters |