Skip to main content

Migration guide from v1.0.0 (REST) to v2.0.0

Overview

This guide provides a comprehensive overview of migrating from our existing v1.0.0 REST API to the new v2.0.0 GraphQL based API. The transition to GraphQL is designed to enhance flexibility, efficiency, and ease of use for developers, offering a more powerful and versatile way to interact with our data services.

If you are new to GraphQL, we recommend visiting our Quickstart Guide for a comprehensive introduction and detailed information on how it works.

Please note that these examples represent only a subset of the changes in the API. However, the new API is powerful and provides more detailed information than the previous version. Therefore, we highly recommend reviewing the entirety of the API documentation for a thorough overview of all available queries and mutations.

Important Basis

  • In our marketplace model, an order placed by a customer, with N products, can be served by N partners. In that case, internally, we generate an "Order" with N "SubOrders", being a SubOrder each part of the Order corresponding to each Partner. The concept of "Order Line" is deprecated. Each partner will only have access to its "part of the order", but will see it represented in the form of a SubOrder.

  • In version 1.0, a lot of operations were done with the Order Code, the identification code of the order placed by the customer, in alphanumeric format like this (5QZJ5). This Order Code is now deprecated. In the new version, the only valid and unique identifier for an order is in UUID format.

Authentication

In the previous REST API, authentication was managed through an API key provided by our customer support team. This key was included in the headers of each request to authenticate the user. In our new GraphQL API, we are transitioning to using JSON Web Tokens (JWT) for authentication, which offers several advantages over the API key authentication method:

  • Enhanced Security: JWTs are signed and optionally encrypted, ensuring the authenticity and integrity of the token.
  • Stateless Authentication: JWTs are self-contained and do not require server-side sessions, reducing the load on the server.
  • Scalability: JWTs can be easily used across different servers and services without the need for a centralized authentication store.
  • Expiration Control: JWTs have built-in expiration, which enhances security by limiting the token’s lifespan.

If you need more information about JSON Web Tokens, please visit the official documentation.

v1.0.0

In the old REST API, the authentication flow was as follows:

  1. Obtain API Key: The API key was provided by our customer support team.
  2. Include API Key in Requests: The API key was included in the headers of each API request as shown below:
GET /orders
Headers:
{
"apikey": "YOUR_API_KEY"
}

v2.0.0

In the new GraphQL API, the authentication flow will be updated to use JWTs. Here’s how the new process works:

  1. Login to Obtain JWT:

    • The client requests for an application token with user credentials.
    • The server validates the credentials and returns a JWT.

    Example request:

    mutation GetApplicationToken($username: String!, $password: String!) {
    getApplicationToken(username: $username, password: $password) {
    tokens {
    accessToken {
    value
    expiresIn
    }
    refreshToken {
    value
    expiresIn
    }
    }
    errors {
    code
    message
    }
    }
    }

    Example response:

    {
    "data":{
    "getApplicationToken":{
    "tokens": {
    "accessToken": {
    "value": "eyJhbGciOiJSUz...",
    "expiresIn": 1800
    }
    "refreshToken" {
    "value": "eyJhbGciOiJSUz...",
    "expiresIn": 1800
    }
    }
    }
    }
    }
  2. Include JWT in Requests:

    • The JWT is included in the headers of each GraphQL request.

    Example request:

    query Query($orderId: ID!) {
    order(id: $orderId) {
    id
    }
    }

    Variables:

    {
    "orderId": "7f718a2e-6396-4735-a111-173a874a68fb"
    }

    Headers:

    {
    "Authorization": "Bearer eyJhbGciO...",
    "locale": "es_ES"
    }

    Example response:

    {
    "data": {
    "order": {
    "id": "7f718a2e-6396-4735-a111-173a874a68fb"
    }
    }
    }
  3. Token Verification:

    • The server verifies the JWT in each request to ensure it is valid and not expired.

Search Orders

v1.0.0

In the old REST API, we get a list of orders through the /orders endpoint:

Example request:

GET /orders
Headers:
{
"apikey": "YOUR_API_KEY"
}

Example response:

{

"total":153,
"results":25,
"page":1,
"orders":[
{
"data":{
"order_id":"124S6",
"order_date":"2018-10-15T22:38:38+00:00",
"number_of_order_lines":3,
"total_amount":10.25,
"currency":"EUR",
"courier":"MRW",
"customer_name":"JOHN DOE",
"customer_country":"ES"
},
"metadata":{
"links":[
{
"rel":"self",
"href":"/orders/164S6"
},
{
"rel":"lines",
"href":"/orders/164S6/lines"
}
]
}
},
...
]

}

v2.0.0

In the new GraphQL API, we will use the query Orders:

Example request:

query Orders($pagination: PaginationArgs, $filters: OrdersFilter) {
orders(pagination: $pagination, filters: $filters) {
collection {
id
code
approvedAt
updatedAt
user {
id
profile {
birthday
gender
email
}
}
shippingAddress {
name
lastName
street
streetNumber
city
administrativeArea
postalCode
country
phone
}
billingAddress {
name
lastName
street
streetNumber
city
administrativeArea
postalCode
country
phone
}
subOrders {
id
seller {
externalId
}
items {
id
unitsToSend
product {
id
name
nationalCodes {
code
acronym
country
}
eans {
code
}
}
unitPrice {
amount
currency
}
}
totalPricePerUnitsToSend {
amount
currency
}
totalPriceWithDiscountPerUnitsToSendWithShippingCosts {
amount
currency
}
shipments {
delivery {
commitment
type
}
timeSlot {
from
to
}
courier {
id
name
}
trackingNumber
}
}
}
metadata {
totalItems
totalPages
currentPage
}
}
}

Variables:

{
"pagination": {
"page": 1,
"size": 2
},
"filters": {
"code": {
"eq": null
},
"hasShipment": {
"eq": null
},
"id": {
"eq": null
},
"itemStatus": null,
"updatedAt": {
"from": null,
"to": null
},
"sort": {
"criteria": [
{
"field": "created_at",
"type": "DESC"
}
]
}
}
}

Headers:

{
"Authorization": "Bearer eyJhbGciO...",
"locale": "es_ES"
}

Example response:

{
"data": {
"orders": {
"collection": [
{
"id": "e8138eb0-823f-4141-aa06-7768f29c2e27",
"code": "6",
"approvedAt": "2023-07-23T19:40:42+0000",
"updatedAt": "2023-07-23T19:40:42+0000",
"user": {
"id": "b1048b4d-1ffb-43dd-ae7f-49d458d525ac",
"profile": {
"birthday": null,
"gender": null,
"email": ""
}
},
"shippingAddress": {
"name": "Albert",
"lastName": "Einstein",
"street": "Preysingstr.",
"streetNumber": "1234",
"city": "München",
"administrativeArea": null,
"postalCode": "81667",
"country": "DE",
"phone": "611111111"
},
"billingAddress": {
"name": "Albert",
"lastName": "Einstein",
"street": "Preysingstr.",
"streetNumber": "1234",
"city": "München",
"administrativeArea": null,
"postalCode": "81667",
"country": "DE",
"phone": "611111111"
},
"subOrders": [
{
"id": "64aa9541-5b00-41b3-94b8-27f670251352",
"seller": {
"externalId": "8384d54d-ed52-440a-88a7-c1bb0e4ce4ce"
},
"items": [
{
"id": "88361e88-2d71-4ec0-ae73-1e5fb431266b",
"unitsToSend": 1,
"product": {
"id": "d1f43aaa-4ca9-4038-a6d5-f26724097f36",
"name": "Hyabak Augentropfen BPC",
"nationalCodes": [
{
"code": "20006033",
"acronym": "pzn",
"country": "DE"
}
],
"eans": [
{
"code": "2000600000033"
}
]
},
"unitPrice": {
"amount": 5.5,
"currency": "EUR"
}
}
],
"totalPricePerUnitsToSend": {
"amount": 5.5,
"currency": "EUR"
},
"totalPriceWithDiscountPerUnitsToSendWithShippingCosts": {
"amount": 11.45,
"currency": "EUR"
},
"shipments": []
}
]
},
{
"id": "f0f4f1e0-6f1d-4a40-aa90-2db819ba7b9a",
"code": "7",
"approvedAt": "2023-07-23T19:37:42+0000",
"updatedAt": "2023-07-23T19:37:42+0000",
"user": {
"id": "b1048b4d-1ffb-43dd-ae7f-49d458d525ac",
"profile": {
"birthday": null,
"gender": null,
"email": ""
}
},
"shippingAddress": {
"name": "Boris",
"lastName": "Becker",
"street": "Bundesstraße",
"streetNumber": "321",
"city": "Berlin",
"administrativeArea": null,
"postalCode": "10115",
"country": "DE",
"phone": "633333333"
},
"billingAddress": {
"name": "Boris",
"lastName": "Becker",
"street": "Bundesstraße",
"streetNumber": "321",
"city": "Berlin",
"administrativeArea": null,
"postalCode": "10115",
"country": "DE",
"phone": "633333333"
},
"subOrders": [
{
"id": "df07dac6-620d-4910-9286-e01527e266a4",
"seller": {
"externalId": "8384d54d-ed52-440a-88a7-c1bb0e4ce4ce"
},
"items": [
{
"id": "c2cc9a39-e6af-485c-b616-e537429fb678",
"unitsToSend": 2,
"product": {
"id": "d1f43aaa-4ca9-4038-a6d5-f26724097f36",
"name": "Hyabak Augentropfen BPC",
"nationalCodes": [
{
"code": "20006033",
"acronym": "pzn",
"country": "DE"
}
],
"eans": [
{
"code": "2000600000033"
}
]
},
"unitPrice": {
"amount": 5.5,
"currency": "EUR"
}
}
],
"totalPricePerUnitsToSend": {
"amount": 11,
"currency": "EUR"
},
"totalPriceWithDiscountPerUnitsToSendWithShippingCosts": {
"amount": 16.95,
"currency": "EUR"
},
"shipments": []
}
]
}
],
"metadata": {
"totalItems": 9,
"totalPages": 5,
"currentPage": 1
}
}
}
}

Get Order and Get Order Lines

v1.0.0

In the old REST API, we get an order through the /orders/{order_id} endpoint and list the lines inside an order with /orders/{order_id}/lines:

Example request:

GET /orders/124S6
Headers:
{
"apikey": "YOUR_API_KEY"
}

Example response:

{
"data":{
"order_id":"124S6",
"order_date":"2018-10-15T22:38:38+00:00",
"number_of_order_lines":3,
"total_amount":10.25,
"currency":"EUR",
"courier":"MRW",
"customer_name":"JOHN DOE",
"customer_country":"ES"
},
"metadata":{
"links":[
{
"rel":"lines",
"href":"/orders/164S6/lines"
}
]
}
}

v2.0.0

In the new GraphQL API, we will use the query Order to retrieve an order and its associated line items. The line items are returned as an attribute of the order in subOrders->items, which contains an array of items within the order.

Example request:

query Query($orderId: ID!) {
order(id: $orderId) {
id
code
approvedAt
user {
profile {
email
birthday
}
}
subOrders {
id
seller {
externalId
}
shipments {
delivery {
commitment
type
}
timeSlot {
from
to
}
}
unitsToSend
totalPricePerUnitsToSend {
amount
currency
}
totalPriceWithDiscountPerUnitsToSendWithShippingCosts {
amount
currency
}
items {
id
product {
id
name
nationalCodes {
acronym
code
country
}
}
unitPrice {
amount
currency
}
unitsToSend
}
}
}
}

Variables:

{
"orderId": "7f718a2e-6396-4735-a111-173a874a68fb"
}

Headers:

{
"Authorization": "Bearer eyJhbGciO...",
"locale": "es_ES"
}

Example response:


{
"data": {
"order": {
"id": "7f718a2e-6396-4735-a111-173a874a68fb",
"code": "2ju5",
"approvedAt": "2023-05-30T11:11:48+0000",
"seller": {
"externalId": "6edd791d-3c2b-49f1-af54-5ff72da7d012"
},
"user": {
"profile": {
"email": "mail@domain.com",
"birthday": "1995-05-30"
}
},
"subOrders": [
{
"id": "f1ed80b7-2512-409d-b181-4c3d75a6f821",
"shipments": [
{
"delivery": {
"commitment": "standard",
"type": "address_delivery"
},
"timeSlot": {
"from": null,
"to": null
}
}
],
"unitsToSend": 2,
"totalPricePerUnitsToSend": {
"amount": 18.9,
"currency": "EUR"
},
"totalPriceWithDiscountPerUnitsToSendWithShippingCosts": {
"amount": 22.4,
"currency": "EUR"
},
"items": [
{
"id": "f3eab1c0-c659-4af0-84ef-4562f671081b",
"product": {
"id": "27db58b3-9852-46b4-86ce-c4b25e8b5847",
"name": "32645.1 OTC",
"nationalCodes": [
{
"acronym": "pzn",
"code": "20006014",
"country": "DE"
}
]
},
"unitPrice": {
"amount": 9.45,
"currency": "EUR"
},
"unitsToSend": 2
}
]
}
]
}
}
}

Notify Shipment Pickup

v1.0.0

In the old REST API, we perform the pickup request so the couriers are aware that order is prepared through the /shipment/{shipment_id}/request-pickup endpoint, where the shipment_id is the same value that the order_id aforementioned in getOrder and getOrderLines endpoints.

Example request:

POST /shipment/124S6/request-pickup
Headers:
{
"apikey": "YOUR_API_KEY"
}

Example response:

{
"metadata":{
"links":[
{
"rel":"order",
"href":"/orders/164S6"
},
{
"rel":"lines",
"href":"/orders/164S6/lines"
}
]
}
}

v2.0.0

In the new GraphQL API, we will use the query NotifyShipmentPickup:

Example request:

mutation NotifyShipmentPickup(
$orderId: ID!,
$subOrderId: ID!,
$sellerId: ID!,
$products: [NotifyShipmentPickupProductsInput!]!,
$courierId: ID,
$trackingNumber: String
) {
notifyShipmentPickup(
orderId: $orderId,
subOrderId: $subOrderId,
sellerId: $sellerId,
products: $products,
courierId: $courierId,
trackingNumber: $trackingNumber
) {
message
errors {
message
code
}
}
}

Variables:

{
"orderId": "0edd74ac-7f9d-4f39-9ba4-f382544f9b0e",
"subOrderId": "9053ec00-a2f6-4132-ab21-172a2b9c6f07",
"sellerId": "50dc2608-401a-4d8e-a885-63cbb2f974b7",
"products": [
{
"productId": "d4488544-fb10-4be9-8cec-a349662b2c47",
"quantity": 1
}
],
"courierId": "5d6b9ec5-8c31-4e2d-add4-5cdc1826eb5e",
"trackingNumber": "DE546323125646"
}

Headers:

{
"Authorization": "Bearer eyJhbGciO...",
}

Example response:

{
"data": {
"notifyShipmentPickup": {
"errors": [],
"message": "SUCCESS"
}
}
}

Get Shipping Label and Get Shipping Waybill

v1.0.0

In the old REST API, we can get the shipping label or shipping waybil as a base-64 encoded pdf with the /shipment/{shipment_id}/label and /shipment/{shipment_id}/label endpoints, where the shipment_id is the same value that the order_id aforementioned in getOrder and getOrderLines endpoints.

Example request:

GET /shipment/124S6/label
Headers:
{
"apikey": "YOUR_API_KEY"
}
GET /shipment/124S6/waybill
Headers:
{
"apikey": "YOUR_API_KEY"
}

Example response:

{
"result": "OK",
"data": "JVBERi0xL..."
}

v2.0.0

In the new GraphQL API, we will use the query Order to get the label and the shipment waybill. Note that these values will be available inside the shipment object only if you have previously requested the Notify Shipment Pickup mutation; otherwise, the shipment object will be null.

Example request:

query Query($orderId: ID!) {
order(id: $orderId) {
id
subOrders {
id
shipments {
label
shipmentWaybill
}
}
}
}

Variables:

{
"orderId": "7f718a2e-6396-4735-a111-173a874a68fb"
}

Headers:

{
"Authorization": "Bearer eyJhbGciO...",
"locale": "es_ES"
}

Example response:


{
"data": {
"order": {
"id": "7f718a2e-6396-4735-a111-173a874a68fb",
"subOrders": [
{
"id": "f1ed80b7-2512-409d-b181-4c3d75a6f821",
"shipments": [
{
"label": "JVBERi0xLjMKM...",
"shipmentWaybill": "SCl0KL0NvdW..."
}
]
}
]
}
}
}