Skip to main content
GET
/
v2
/
payment-links
/
{id}

Get Payment Link

Retrieve information about a payment link, including its current status and payment details.

Authentication

Authorization: Bearer glm_test_YOUR_API_KEY

Path Parameters

ParameterTypeRequiredDescription
idstringYesPayment link ID (e.g., plink_abc123xyz)

Request

GET /v2/payment-links/{id}

Response

{
  "id": "plink_abc123xyz",
  "url": "https://checkout.withgale.com/pay/plink_abc123xyz",
  "amount_cents": 4995,
  "currency": "USD",
  "description": "Premium Blood Pressure Monitor",
  "payment_type": "one_time",
  "status": "paid",
  "customer": {
    "email": "customer@example.com",
    "first_name": "Jane",
    "last_name": "Doe"
  },
  "products": [
    {
      "merchant_product_id": "BP-MONITOR-001",
      "name": "Blood Pressure Monitor",
      "quantity": 1,
      "price_cents": 4995,
      "is_hsa_fsa_eligible": true,
      "eligibility_type": "auto_substantiation"
    }
  ],
  "order": {
    "id": "ord_xyz789",
    "status": "completed",
    "paid_at": "2025-10-18T15:30:00Z"
  },
  "success_url": "https://yoursite.com/success",
  "cancel_url": "https://yoursite.com/cancel",
  "metadata": {
    "order_id": "ORD-12345",
    "customer_id": "CUST-789"
  },
  "expires_at": "2025-11-02T14:30:00Z",
  "created_at": "2025-10-18T14:30:00Z",
  "paid_at": "2025-10-18T15:30:00Z"
}

Response Fields

FieldTypeDescription
idstringUnique payment link identifier
urlstringCheckout URL for the payment link
amount_centsintegerTotal amount in cents
statusenumactive, paid, expired, or cancelled
orderobjectAssociated order (if paid)
order.idstringOrder ID
order.statusenumOrder status
order.paid_attimestampWhen payment was completed
paid_attimestampWhen link was paid (null if not paid)

Examples

Basic Retrieval

curl https://api.withgale.com/v2/payment-links/plink_abc123xyz \
  -H "Authorization: Bearer glm_test_YOUR_API_KEY"

Check Payment Status

const checkPaymentStatus = async (linkId) => {
  const response = await fetch(
    `https://api.withgale.com/v2/payment-links/${linkId}`,
    {
      headers: {
        'Authorization': `Bearer ${process.env.GALE_API_KEY}`
      }
    }
  );

  const link = await response.json();

  if (link.status === 'paid') {
    console.log(`Payment completed! Order ID: ${link.order.id}`);
    return link.order;
  } else if (link.status === 'expired') {
    console.log('Payment link expired');
    return null;
  } else {
    console.log('Payment pending');
    return null;
  }
};
const getSubscriptionLink = async (linkId) => {
  const response = await fetch(
    `https://api.withgale.com/v2/payment-links/${linkId}`,
    {
      headers: {
        'Authorization': `Bearer ${process.env.GALE_API_KEY}`
      }
    }
  );

  const link = await response.json();

  if (link.payment_type === 'subscription' && link.status === 'paid') {
    return {
      subscriptionId: link.subscription.id,
      customerId: link.order.customer.id,
      nextBilling: link.subscription.next_billing_date
    };
  }
};

Active

Link is ready to accept payment and has not expired.
{
  "status": "active",
  "expires_at": "2025-11-02T14:30:00Z",
  "paid_at": null,
  "order": null
}
Payment was completed successfully.
{
  "status": "paid",
  "paid_at": "2025-10-18T15:30:00Z",
  "order": {
    "id": "ord_xyz789",
    "status": "completed"
  }
}

Expired

Link expired without payment.
{
  "status": "expired",
  "expires_at": "2025-10-18T14:30:00Z",
  "paid_at": null,
  "order": null
}

Cancelled

Link was manually cancelled.
{
  "status": "cancelled",
  "cancelled_at": "2025-10-18T16:00:00Z",
  "cancellation_reason": "Customer requested cancellation"
}

Errors

Status CodeError CodeDescription
401unauthorizedInvalid or missing API key
404not_foundPayment link not found
429rate_limit_exceededToo many requests
Example error:
{
  "error": {
    "code": "not_found",
    "message": "Payment link not found",
    "param": "id"
  }
}

Use Cases

Order Fulfillment

// Check if payment link is paid before shipping
app.get('/orders/:linkId/fulfill', async (req, res) => {
  const link = await getPaymentLink(req.params.linkId);

  if (link.status !== 'paid') {
    return res.status(400).json({
      error: 'Payment not completed'
    });
  }

  // Fulfill order
  await shipOrder(link.order.id);

  res.json({
    message: 'Order fulfilled',
    tracking: '1Z999AA10123456784'
  });
});

Customer Portal

// Display payment status in customer portal
const renderInvoiceStatus = async (linkId) => {
  const link = await getPaymentLink(linkId);

  return {
    invoiceNumber: link.metadata.invoice_number,
    amount: link.amount_cents / 100,
    status: link.status,
    paidAt: link.paid_at,
    receiptUrl: link.order?.receipt_url
  };
};

Webhook Verification

// Verify webhook event by checking link status
app.post('/webhooks/gale', async (req, res) => {
  const event = req.body;

  if (event.type === 'payment_link.paid') {
    // Double-check by fetching link
    const link = await getPaymentLink(event.data.id);

    if (link.status === 'paid' && link.order) {
      await fulfillOrder(link.order.id);
    }
  }

  res.status(200).send('OK');
});

Best Practices

Use Webhooks

Don’t poll this endpoint. Use webhooks for real-time notifications.

Verify Before Fulfillment

Always verify status === 'paid' before fulfilling orders.

Handle All Statuses

Account for expired and cancelled states in your logic.

Cache Responses

Cache paid links to reduce API calls.