by InlinexDev

Building an International Shipping Platform with FedEx API and Stripe

How we built ShipAnywhere, a full-stack shipping platform integrating FedEx rates, label generation, Stripe wallets, and Shopify order sync.

FedEx APIStripeShopifyNode.jsshipping

The Challenge

Small e-commerce merchants in Southeast Asia face a common problem: international shipping is expensive and complicated. They need to compare rates, generate labels, track packages, and manage shipping costs — all while keeping their Shopify store in sync. ShipAnywhere was built to solve exactly this.

Architecture Overview

ShipAnywhere is a Node.js/Express application backed by PostgreSQL, deployed on Railway. It connects three major external services:

  • FedEx API — real-time rate quotes and label generation
  • Stripe — prepaid wallet system for shipping credits
  • Shopify API — order import and fulfillment tracking

The Wallet Model

Rather than charging per shipment via credit card (which adds friction and processing fees), ShipAnywhere uses a prepaid wallet system. Merchants top up their balance via Stripe, and shipping costs are deducted from the wallet. This approach:

  • Reduces per-transaction payment fees
  • Enables instant label generation without payment delays
  • Simplifies refunds when shipments are cancelled

FedEx API Integration

FedEx's REST API replaced their legacy SOAP services. Here's how we handle rate shopping:

async function getRates(shipment) {
  const token = await getFedExToken();
  
  const response = await axios.post(
    `${FEDEX_BASE_URL}/rate/v1/rates/quotes`,
    {
      accountNumber: { value: FEDEX_ACCOUNT },
      requestedShipment: {
        shipper: formatAddress(shipment.from),
        recipient: formatAddress(shipment.to),
        requestedPackageLineItems: [{
          weight: { value: shipment.weight, units: 'KG' },
          dimensions: {
            length: shipment.length,
            width: shipment.width,
            height: shipment.height,
            units: 'CM'
          }
        }]
      }
    },
    { headers: { Authorization: `Bearer ${token}` } }
  );

  return response.data.output.rateReplyDetails.map(rate => ({
    service: rate.serviceName,
    deliveryDays: rate.commit?.dateDetail?.dayFormat,
    cost: rate.ratedShipmentDetails[0].totalNetCharge
  }));
}

Token Management

FedEx OAuth tokens expire after 60 minutes. We cache them in memory with a buffer:

let cachedToken = null;
let tokenExpiry = 0;

async function getFedExToken() {
  if (cachedToken && Date.now() < tokenExpiry - 60000) {
    return cachedToken;
  }
  const response = await axios.post(`${FEDEX_BASE_URL}/oauth/token`, {
    grant_type: 'client_credentials',
    client_id: FEDEX_CLIENT_ID,
    client_secret: FEDEX_CLIENT_SECRET
  });
  cachedToken = response.data.access_token;
  tokenExpiry = Date.now() + (response.data.expires_in * 1000);
  return cachedToken;
}

Shopify Order Sync

When a merchant connects their Shopify store, ShipAnywhere imports unfulfilled orders and listens for new ones via webhooks. After a label is generated, the app automatically:

  1. Marks the Shopify order as fulfilled
  2. Adds the FedEx tracking number
  3. Triggers Shopify's shipping confirmation email

This eliminates the manual copy-paste workflow that merchants were doing before.

Document Storage with Cloudflare R2

Shipping labels and commercial invoices are stored in Cloudflare R2, an S3-compatible object store. R2 was chosen over AWS S3 for its zero egress fees — since labels are downloaded frequently, this saved significant costs.

const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');

const r2Client = new S3Client({
  region: 'auto',
  endpoint: process.env.R2_ENDPOINT,
  credentials: {
    accessKeyId: process.env.R2_ACCESS_KEY,
    secretAccessKey: process.env.R2_SECRET_KEY
  }
});

async function uploadLabel(buffer, filename) {
  await r2Client.send(new PutObjectCommand({
    Bucket: process.env.R2_BUCKET,
    Key: `labels/${filename}`,
    Body: buffer,
    ContentType: 'application/pdf'
  }));
}

Key Technical Decisions

  • PostgreSQL over MongoDB — shipping data is highly relational (orders, shipments, addresses, invoices)
  • Railway over AWS — faster deployment cycles for a small team, built-in PostgreSQL
  • Prepaid wallet over per-transaction billing — reduced Stripe fees and better UX
  • Cloudflare R2 over S3 — zero egress fees for frequently accessed labels

Results

ShipAnywhere reduced the time from order receipt to label generation from 15+ minutes (manual process) to under 30 seconds. Merchants can now batch-process dozens of shipments and have all labels ready in minutes.

Related Project

ShipAnywhere

Smart international shipping platform offering up to 60% off FedEx rates, with instant quotes, one-click labels, electronic trade documents, and scheduled pickups to 220+ countries.