For developers

Welcome

Welcome to Droppas developer toolkit!
This API lets you integrate Droppa using our return registration UI, as a shipping provider for your P2P retail service or as the logistics provider for your shipping service.

Next step

In order to start experimenting with the API, you need a test account. Connect with to sales.
Check out our example integration flows.
Contact sales

Integration Examples:

Returns handling using the Droppa software

Api References:

Rest API
Graph QL Api

Returns handling using the Droppa software

The integration of Droppas return service relies on integrating the Droppa public APIs. These APIs consist of two parts, the GraphQL API and the webhooks.

The GQL API will mainly be used for passing data to Droppa that is needed to handle returns. This contains information like Orders, Products and Customers. If the return interface is build by the merchant themselves also the Return is added through the GQL API.

The webhooks are used to notify the merchant of events from inside of Droppa. These events are Return Created and tracking events.

Typical integration flows

Pre-Return Registration

  • As a product is added or updated → Product information is added to Droppa using the mutation addProduct or addProducts.
  • As an order is placed → Order information is added to Droppa using the mutation addOrder or addOrders.

Return Registration

  • The order information is gotten from droppa using the GQL API.
  • The information is rendered in the UI, either using the Droppa return booking software or custom built by the merchant.
  • The customer goes through the return booking flow.
  • A return is added using the addReturn or addReturns mutation.
  • A return webhook (Return Created) is sent to the URL configured by the merchant.

Post-Return Registration (Droppa dropspots only)

  • The return is send to the Droppa hub.
  • The items are scanned and sorted.
  • The items are put on pallets and sent back to the merchant. At the same time a PO is registered in the merchant WMS.

P2P Retail Example

In this example, we will describe the integration needed to become a P2P partner with Droppa.
In order to use this endpoint you should be registered in our system. Please contact our sales

Step by step:

Check if the sender's address is within the pickup zone using the canShipFromRequest
POST
fetch(
   '<https://rpc.droppa.dev/rpc/p2p/canShipFrom>',
   {
       method: "POST",
       headers: {
           Authorization: "Bearer YOUR_TOKEN"
       },
       body: JSON.stringify({
          "sender":{
              "address": "Elins gård",
              "country": "SE",
              "postalCode": "41481",
              "type": "Address"
          }
       })
   })
   .then(response => response.json())
   .then(response => console.log(response))
RESPONSE
{ available: false }

**canShipFrom** Error Messages

Request type is not Address or Coordinates:
{
   error: "InvalidSenderLocationType",
   scope: ["p2p"],
   level: "Input",
   objectName: "SENDER_TYPE",
   message: "The sender location type is not supported."
}
Check if the recipient’s address is within the pickup zone using the canShipTo
POST
fetch(
   '<https://rpc.droppa.dev/rpc/p2p/canShipTo>',
   {
       method: "POST",
       headers: {
           Authorization: "Bearer YOUR_TOKEN"
       },
       body: JSON.stringify({
          "recipient":{
              "address": "Krukmakargatan 2",
              "country": "SE",
              "postalCode": "11726"
          }
       })
   })
   .then(response => response.json())
   .then(response => console.log(response))
RESPONSE
{ available: true }

**canShipTo** Error Messages

Malformed postal code results in:
{
   error: "InvalidPostalCode",
   scope: ["p2p"],
   level: "Input",
   message: "Could not look up postal code"
}
Book a shipment using ship
POST
fetch(
   '<https://rpc.droppa.dev/rpc/p2p/ship>',
   {
       method: "POST",
       headers: {
           Authorization: "Bearer process.env.DROPPA_TOKEN"
       },
       body: JSON.stringify({
          sender
:{
            contactInfo: {
              emailAddress: "your@email.com",
              phoneNumber: "+44444444444"
            
}
          },
           recipient:{
             contactInfo:{
               emailAddress: "your@email.com",
               phoneNumber: "+44444444444"
             },
             address:{
               name: "Your Name",
               street:
"Street name",
               postalCode:
"22222",
               country:
"SE"
             
},
             product:{
               value: {
                 currency:
"SEK",
                 amount:
"0",
               },
               size: "S",
             },
          },
          webhookUrl: "<https://google.com>"
       })
   })
   .then(response => response.json())
   .then(response => console.log(response))
RESPONSE
{
   "id": "YOUR_SHIPMENT_ID",
   "senderStatusUrl": "STATUS_URL",
   "recipientStatusUrl": "STATUS_URL",
   "qrCodeImageUrl": "QR_CODE_URL"
}

**ship** Error Messages

Empty contact information field for either Sender or Recipient results in:
{
   error: "**Recipient**ContactInformationNotFound",
   scope: ["p2p"],
   level: "Input",
   objectName: {email: "EMAIL", phoneNumber: "PHONE_NUMBER"},
   message: "**Recipient** contact Information not found."
}
Empty address information for Recipient results in:
{
   error: "RecipientAddressInformationNotFound",
   scope: ["p2p"],
   level: "Input",
   objectName: {
     name: "RECIPIENT_NAME";
     street: "STREET"
     postalCode: "POSTAL_CODE";
     careOf: "NAME" | null;
     country: "COUNTRY_CODE";
   
}, | null,
   message: "Recipient address not found."
}
Malformed postalCode results in:
{
   error: "InvalidRecipientAddressInformation",
   scope: ["p2p"],
   level: "Input",
   objectName: {
     value: {currency: "CURRENCY", amount: "AMOUNT"}
,
     size: "SIZE"
   
},
   message: "Product information not valid."
}
Empty product information results in:
{
   error: "ProductInformationNotFound",
   scope: ["p2p"],
   level: "Input",
   objectName: {...},
   message: "Recipient address information not valid: Malformed postal code."
}
Empty webhook results in:
{
   error: "WebhookUrlNotFound",
   scope: ["p2p"],
   level: "Input",
   objectName: "YOUR_WEBHOOK",
   message: "Webhook URL not found."
}
 If the id is invalid:
{
   error: "InvalidId",
   scope: ["p2p"],
   level: "Input",
   objectName: id,
   message: "The ID is invalid."
}
If no id was provided:
{
   error: "IdNotFound",
   scope: ["p2p"],
   level: "Input",
   objectName: id,
   message: "Id not found in database"
}
 No platform provided:
POST
{
   error: "PlatformNotFound",
   scope: ["p2p"],
   level: "Internal",
   message: "No platform found for token."
}
Check status of the shipment with getStatus
POST
fetch(
   '<https://rpc.droppa.dev/rpc/p2p/getStatus>',
   {
       method: "POST",
       headers: {
           Authorization: "Bearer YOUR_TOKEN"
       },
       body: JSON.stringify({id: 'YOUR_SHIPMENT_ID"})
   })
   .then(response => response.json())
   .then(response => console.log(response))
RESPONSE
{
   "state": "NotDroppedOff",
   "senderStatusUrl": "<https://app.droppa.dev/p2p/sender/YOUR_SHIPMENT_ID>",
   "recipientStatusUrl": "<https://app.droppa.dev/p2p/recipient/YOUR_SHIPMENT_ID>",
   eta: null
}

getStatus Error Messages

If the token doesn’t exist:
{
   error: "InvalidToken",
   scope: ["Auth"],
   level: "Input",
   objectName: {"YOUR_REQUEST"},
   message: "The token is invalid."
}
If the ID is invalid:
{
   error: "InvalidId",
   scope: ["p2p"],
   level: "Input",
   objectName: id,
   message: "The ID is invalid."
}
If no id was provided:
{
   error: "IdNotFound",
   scope: ["p2p"],
   level: "Input",
   objectName: id,
   message: "Id not found in database"
}
No platform provided:
{
   error: "PlatformNotFound",
   scope: ["p2p"],
   level: "Internal",
   message: "No platform found for token."
}
Clients:
We have clients for Typescript and Scala to download. Contact our sales.

Network Return Example

In this example, we will describe the integration needed to integrate a merchant with Droppas network without using Droppas booking form.
IMPORTANT: In order to use this endpoint you should be registered in our system. Please contact our sales

Step by step:

Check the distance from kiosk to sender's address with the pickup using findClosestKioskByPostCode. The response will contain the closest Kiosk and how far it is.
POST
fetch(
   '<https://rpc.droppa.dev/rpc/kiosk/findClosestKioskByPostcode>',
   {
       method: "POST",
       headers: {
           Authorization: "Bearer YOUR_TOKEN"
       },
       body: JSON.stringify({
          "country"
: "SE",
           "lat": 0,
          "lng": 0,
          "distance": 0,
          "offset": 0,
          "limit": 0,
       })
   })
   .then(response => response.json())
   .then(response => console.log(response))
RESPONSE
{
  "response"
: {
    "kiosk": {
       "id": "string",
       "name": "string",
       "address": {
         "name": "string",
         "addressLine1": "string",
         "addressLine2": "string",
         "addressLine3": "string",
         "addressLine4": "string",
         "city": "string",
         "region": "string",
         "country": "string",
         "postcode": "string",
         "location": {
           "type": "string",     
           "coordinates": [
            0
           ]   
         }
       },
      "phoneNumber": "string",
      "emailAddress": "string",
      "createdAt": "string",
      "updatedAt": "string",
      "pressbyranId": "string",
      "isActive": true
    },
    "distance": 0,
  }
}

**findClosestKiosk** Error Messages

{
   error: "string",
   scope: ["kiosk"],
   level: "Input"
}
Book a return using returnCreate
POST
fetch(
   '<https://rpc.droppa.dev/rpc/returns/returnCreate>',
   {
       method: "POST",
       headers: {
           Authorization: "Bearer process.env.DROPPA_TOKEN"
       },
       body: JSON.stringify({
          "type"
: "Network",
           "order": {
             "orderNumber"
: "string",
             "merchantId": "string",
             "merchantName": "string",
          
},
           "refunds": [
             {
             "count"
: 0,
             "reason": "string",
             "article": {
               "name": "string",
               "barcode":
"string",
               "productId": "string",
               "variantId":
"string",
               "image": {
                 "url": "string",
                 "name": "string",
                 mimeType":
"string",
                 alternate": "string"
               }
             }
           
}
         ],
           "exchanges": [
             {
             "productId"
: string,
             "productName": "string",
             "oldVariant": {
               "id": "string",
               "name":
"string",
               "barcode": "string",
             }
             "newVariant": {
               "id": "string",
               "name":
"string",
               "barcode": "string",
             },
             "reason": "string"
           
}
         ],
         "customerEmail": "string"
         
}
      })
   })
   .then(response => response.json())
   .then(response => console.log(response))
RESPONSE
{
   "returnId": "string",
   "shipmentId": 0,
}

**returnCreate** Error Messages

{
   error: "string",
   scope: ["Returns"],
   level: "Input"
}
Get information about the shipment with lookupShipment
POST
fetch(
   '<https://rpc.droppa.dev/rpc/network/lookupShipment>',
   {
       method: "POST",
       headers: {
           Authorization: "Bearer YOUR_TOKEN"
       },
       body: JSON.stringify({shipmentId: "YOUR_SHIPMENT_ID"})
   })
   .then(response => response.json())
   .then(response => console.log(response))
RESPONSE
{
   "deliveryService": "PostNord",
   "bookingId": "string",
   "barcodeUrl": "string",
   "trackingCode": "string",
   "labelType": "PDF",
   "labelData": "string",
   "labelUrl": "string"
}

**findClosestKiosk** Error Messages

{
   error: "string",
   scope: "string",
   level: "string"
}
Clients:
We have clients for Typescript and Scala to download. Contact our sales.