Categorygithub.com/jackharley7/aftership-sdk-go/v2
modulepackage
2.0.2
Repository: https://github.com/jackharley7/aftership-sdk-go.git
Documentation: pkg.go.dev

# README

aftership-sdk-go

Build Status codecov.io GoDoc AfterShip SDKs channel

Introduction

AfterShip provides an API to Track & Notify of shipments from hundreds of couriers worldwide. aftership-sdk-go is a SDK to develop Apps using AfterShip API v4 in golang. All endpoints including couriers, tracking, last checkpoint and notification are supported.

You will need to create an account at AfterShip and obtain an API key first to access AfterShip APIs using aftership-go SDK.

Installation

aftership-sdk-go requires a Go version with Modules support and uses import versioning. So please make sure to initialize a Go module before installing aftership-sdk-go:

go mod init github.com/my/repo
go get github.com/aftership/aftership-sdk-go/v2

Import:

import "github.com/aftership/aftership-sdk-go/v2"

Quick Start

package main

import (
        "context"
        "fmt"

        "github.com/aftership/aftership-sdk-go/v2"
)

func main() {

        client, err := aftership.NewClient(aftership.Config{
                APIKey: "YOUR_API_KEY",
        })

        if err != nil {
                fmt.Println(err)
                return
        }

        // Get couriers
        result, err := client.GetCouriers(context.Background())
        if err != nil {
                fmt.Println(err)
                return
        }

        fmt.Println(result)
}

Test

make test

Table of contents

NewClient(config)

Create AfterShip SDK instance with config

  • config - object of request config
    • APIKey - Required, AfterShip API key
    • Endpoint - string, AfterShip endpoint, default "https://api.aftership.com/v4"
    • UserAagentPrefix - string, prefix of User-Agent in headers, default "aftership-sdk-go"

Example:

client, err := aftership.NewClient(aftership.Config{
    APIKey: "YOUR_API_KEY",
    Endpoint: "https://api.aftership.com/OLDER_VERSIONOUR_API_KEY",
    UserAagentPrefix: "aftership-sdk-go",
})

Rate Limiter

To understand AfterShip rate limit policy, please see Limit section in https://docs.aftership.com/api/4/overview

You can get the recent rate limit by client.GetRateLimit(). Initially all value are 0.

import (
    "context"
    "fmt"

    "github.com/aftership/aftership-sdk-go/v2"
)

func main() {
    client, err := aftership.NewClient(aftership.Config{
        APIKey: "YOUR_API_KEY",
    })

    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(client.GetRateLimit())

    // terminal output
    /*
    {
        "reset": 0,
        "limit": 0,
        "remaining": 0,
    }
    */

    // Get couriers
    result, err := client.GetCouriers(context.Background())
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(result)
    }

    // Rate Limit
    fmt.Println(client.GetRateLimit())

    // terminal output
    /*
    {
        "reset": 1588249242,
        "limit": 10,
        "remaining": 9,
    }
    */
}

In case you exceeded the rate limit, you will receive the 429 Too Many Requests error with the following error message:

{
  "code": 429,
  "type": "TooManyRequests",
  "message": "You have exceeded the API call rate limit. Default limit is 10 requests per second.",
  "path": "/couriers",
  "rate_limit": {
    "rest": 1458463600,
    "limit": 10,
    "remaining": 0
  }
}

Error Handling

There are 3 kinds of error

  • SDK Error
  • Request Error
  • API Error

SDK Error

Throw by the new SDK client

client, err := aftership.NewClient(aftership.Config{
    APIKey: "",
})

if err != nil {
    fmt.Println(err)
    return
}

/*
invalid credentials: API Key must not be empty
*/

Throw by the parameter validation in function

client, err := aftership.NewClient(aftership.Config{
    APIKey: "YOUR_API_KEY",
})

// Get notification
param := aftership.SlugTrackingNumber{
    Slug: "dhl",
}

result, err := client.GetNotification(context.Background(), param)
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

/*
slug or tracking number is empty, both of them must be provided
*/

Request Error

client, err := aftership.NewClient(aftership.Config{
    APIKey: "YOUR_API_KEY",
})

// Get couriers
result, err := client.GetCouriers(context.Background())
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)
/*
HTTP request failed: Get https://api.aftership.com/v4/couriers: dial tcp: lookup api.aftership.com: no such host
*/

API Error

Error return by the AfterShip API https://docs.aftership.com/api/4/errors

API Error struct of this SDK contain fields:

  • Code - error code for API Error
  • Type - type of the error
  • Message - detail message of the error
  • Path - URI path when making request
  • RateLimit - Optional - When the API gets 429 Too Many Requests error, the error struct will return the RateLimit information as well.
client, err := aftership.NewClient(aftership.Config{
    APIKey: "INVALID_API_KEY",
})

// Get couriers
result, err := client.GetCouriers(context.Background())
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)
/*
{
  "code": 401,
  "type": "Unauthorized",
  "message": "Invalid API key.",
  "path": "/couriers"
}
*/

Examples

/couriers

Get a list of our supported couriers.

GET /couriers

Return a list of couriers activated at your AfterShip account.

result, err := client.GetCouriers(context.Background())
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

GET /couriers/all

Return a list of all couriers.

result, err := client.GetAllCouriers(context.Background())
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

POST /couriers/detect

Return a list of matched couriers based on tracking number format and selected couriers or a list of couriers.

params := aftership.CourierDetectionParams{
    TrackingNumber: "906587618687",
}

result, err := client.DetectCouriers(context.Background(), params)
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

/trackings

Create trackings, update trackings, and get tracking results.

POST /trackings

Create a tracking.

newTracking := aftership.NewTracking{
    TrackingNumber: "1234567890",
    Slug:           []string{"dhl"},
    Title:          "Title Name",
    Smses: []string{
        "+18555072509",
        "+18555072501",
    },
    Emails: []string{
        "[email protected]",
        "[email protected]",
    },
    OrderID: "ID 1234",
    CustomFields: map[string]string{
        "product_name":  "iPhone Case",
        "product_price": "USD19.99",
    },
    Language:                  "en",
    OrderPromisedDeliveryDate: "2019-05-20",
    DeliveryType:              "pickup_at_store",
    PickupLocation:            "Flagship Store",
    PickupNote:                "Reach out to our staffs when you arrive our stores for shipment pickup",
}

result, err := client.CreateTracking(context.Background(), newTracking)
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

DELETE /trackings/:slug/:tracking_number

Delete a tracking.

param := aftership.SlugTrackingNumber{
    Slug:           "dhl",
    TrackingNumber: "1234567890",
}

result, err := client.DeleteTracking(context.Background(), param)
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

GET /trackings

Get tracking results of multiple trackings.

multiParams := aftership.GetTrackingsParams{
    Page:  1,
    Limit: 10,
}

result, err := client.GetTrackings(context.Background(), multiParams)
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

GET /trackings/:slug/:tracking_number

Get tracking results of a single tracking.

param := aftership.SlugTrackingNumber{
    Slug:           "dhl",
    TrackingNumber: "1588226550",
}

result, err := client.GetTracking(context.Background(), param, aftership.GetTrackingParams{})
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

Pro Tip: You can always use /:id to replace /:slug/:tracking_number.

// GET /trackings/:id
var id TrackingID = "5b7658cec7c33c0e007de3c5"

result, err := client.GetTracking(context.Background(), id, aftership.GetTrackingParams{})
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

PUT /trackings/:slug/:tracking_number

Update a tracking.

param := aftership.SlugTrackingNumber{
    Slug:           "dhl",
    TrackingNumber: "1588226550",
}

updateReq := aftership.UpdateTrackingParams{
    Title: "New Title",
}

result, err := client.UpdateTracking(context.Background(), param, updateReq)
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

POST /trackings/:slug/:tracking_number/retrack

Retrack an expired tracking. Max 3 times per tracking.

param := aftership.SlugTrackingNumber{
    Slug:           "dhl",
    TrackingNumber: "1588226550",
}

result, err := client.RetrackTracking(context.Background(), param)
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

POST /trackings/:slug/:tracking_number/mark-as-completed

Mark a tracking as completed. The tracking won't auto update until retrack it.

param := aftership.SlugTrackingNumber{
    Slug:           "dhl",
    TrackingNumber: "1588226550",
}

result, err := client.MarkTrackingAsCompleted(context.Background(), param, aftership.TrackingCompletedStatusDelivered)
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

/last_checkpoint

Get tracking information of the last checkpoint of a tracking.

GET /last_checkpoint/:slug/:tracking_number

Return the tracking information of the last checkpoint of a single tracking.

param := aftership.SlugTrackingNumber{
    Slug:           "ups",
    TrackingNumber: "1234567890",
}

result, err := client.GetLastCheckpoint(context.Background(), param, aftership.GetCheckpointParams{})
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

/notifications

Get, add or remove contacts (sms or email) to be notified when the status of a tracking has changed.

GET /notifications/:slug/:tracking_number

Get contact information for the users to notify when the tracking changes.

param := aftership.SlugTrackingNumber{
    Slug:           "dhl",
    TrackingNumber: "1588226550",
}

result, err := client.GetNotification(context.Background(), param)
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

POST /notifications/:slug/:tracking_number/add

Add notification receivers to a tracking number.

param := aftership.SlugTrackingNumber{
    Slug:           "dhl",
    TrackingNumber: "1588226550",
}

data := notification.Data{
    Notification: notification.Notification{
        Emails: []string{"[email protected]", "[email protected]", "invalid EMail @ Gmail. com"},
        Smses:  []string{"+85291239123", "+85261236123", "Invalid Mobile Phone Number"},
    },
}

result, err := client.AddNotification(context.Background(), param, data)
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

POST /notifications/:slug/:tracking_number/remove

Remove notification receivers from a tracking number.

param := aftership.SlugTrackingNumber{
    Slug:           "dhl",
    TrackingNumber: "1588226550",
}

data := notification.Data{
    Notification: notification.Notification{
        Emails: []string{"[email protected]"},
        Smses:  []string{"+85291239123"},
    },
}

result, err := client.RemoveNotification(context.Background(), param, data)
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

Migrations

// old version
var api apiV4.CourierHandler = &impl.AfterShipApiV4Impl{
    "<your-api-key>",
    nil,
    nil,
}
res, meta := api.GetCouriers()
if (meta.Code == 200) {
    fmt.Print(res)
}

// new version (v2)
client, err := aftership.NewClient(aftership.Config{
    APIKey: "YOUR_API_KEY",
})

result, err := client.GetCouriers(context.Background())
if err != nil {
    fmt.Println(err)
    return
}

fmt.Println(result)

Help

If you get stuck, we're here to help. The following are the best ways to get assistance working through your issue:

  • Issue Tracker for questions, feature requests, bug reports and general discussion related to this package. Try searching before you create a new issue.
  • Slack AfterShip SDKs: a Slack community, you can find the maintainers and users of this package in #aftership-sdks.
  • Email us in AfterShip support: [email protected]

Contributing

For details on contributing to this repository, see the contributing guide.

# Functions

NewClient returns the AfterShip client.

# Constants

TrackingCompletedStatusDelivered is reason DELIVERED to make the tracking as completed.
TrackingCompletedStatusLost is reason LOST to make the tracking as completed.
TrackingCompletedStatusReturnedToSender is reason RETURNED_TO_SENDER to make the tracking as completed.
VERSION is the version number of this package.

# Structs

APIError is the error in AfterShip API calls.
Checkpoint represents a checkpoint returned by the Aftership API.
Client is the client for all AfterShip API calls.
Config is the config of AfterShip SDK client.
Courier is the model describing an AfterShip courier.
CourierDetectionParams contains fields required and optional fields for courier detection.
CourierList is the model describing an AfterShip courier list.
CreateTrackingParams provides parameters for new Tracking API request.
GetCheckpointParams is the additional parameters in checkpoint query.
GetTrackingParams is the additional parameters in single tracking query.
GetTrackingsParams represents the set of params for get Trackings API.
LastCheckpoint is the last checkpoint API response.
Meta is used to communicate extra information about the response to the developer.
Notification is the model describing an AfterShip notification.
PagedTrackings is a model for data part of the multiple trackings API responses.
RateLimit is the X-RateLimit value in API response headers.
Response is the message envelope for the AfterShip API response.
SingleTrackingOptionalParams is the optional parameters in single tracking query.
SlugTrackingNumber is a unique identifier for a single tracking by slug and tracking number.
TooManyRequestsError is the too many requests error in AfterShip API calls.
Tracking represents a Tracking returned by the AfterShip API.
TrackingCouriers is the model describing an AfterShip couriers detect list.
UpdateTrackingParams represents an update to Tracking details.

# Interfaces

TrackingIdentifier is an identifier for a single tracking.

# Type aliases

TrackingCompletedStatus is status to make the tracking as completed.
TrackingID is a unique identifier generated by AfterShip for the tracking.