Install & API

Wire up the GreenChain Eco-Receipt widget

Drop the widget on checkout, send a signed POST after payment, and share the proof pages everywhere. Secrets are hashed, requests are HMAC verified, and nothing uses customer PII.

1. Install the widget

Shopify theme snippet

<div class="gc-addon">
  <label class="gc-checkbox">
    <input type="checkbox" id="gc-addon" name="attributes[greenchain_addon]" value="yes" />
    <span>Make my order greener (+99 PKR)</span>
  </label>
</div>
<script>
  document.addEventListener('DOMContentLoaded', function () {
    const input = document.querySelector('#gc-addon');
    if (!input) return;
    input.addEventListener('change', function () {
      window.GreenChainAddonSelected = input.checked;
    });
  });
</script>

Read window.GreenChainAddonSelected after checkout to know if the shopper opted in.

WooCommerce snippet (functions.php)

<?php
add_action('woocommerce_review_order_before_submit', function () {
  echo '<div class="gc-addon">';
  woocommerce_form_field('greenchain_addon', [
    'type'  => 'checkbox',
    'label' => 'Make my order greener (+99 PKR)',
  ], WC()->session->get('greenchain_addon'));
  echo '</div>';
});

add_action('woocommerce_checkout_update_order_meta', function ($order_id) {
  $selected = isset($_POST['greenchain_addon']) ? true : false;
  update_post_meta($order_id, '_greenchain_addon', $selected);
});

Custom stack

Render a checkbox near the order total. Persist the boolean alongside the order. After payment call our REST endpoint with addon_selected reflecting the shopper choice.

<label class="gc-addon">
  <input type="checkbox" id="gc-addon" />
  Make my order greener (+99 PKR)
</label>

2. Sign your payload

Secrets are shown once in the dashboard. Hash them with SHA-256 and use the hash as the HMAC key. This keeps secrets encrypted at rest while preserving deterministic signatures.

import crypto from 'node:crypto';

const body = JSON.stringify({
  projectId: 'proj_123',
  order_id: 'order-9912',
  amount_minor: 124900,
  addon_selected: true,
  weight_grams: 1200,
  ship_from_city: 'Karachi',
  ship_to_city: 'Lahore'
});

const secret = process.env.GC_PROJECT_SECRET!; // gc_sec_xxx
const secretHash = crypto.createHash('sha256').update(secret).digest('hex');
const signature = crypto.createHmac('sha256', Buffer.from(secretHash, 'hex'))
  .update(body)
  .digest('hex');

fetch('https://greenchain.site/api/record-order', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-GC-PUBLIC-KEY': process.env.GC_PUBLIC_KEY!,
    'X-GC-SIGN': signature
  },
  body
});

Headers required:

  • X-GC-PUBLIC-KEY – your project public key.
  • X-GC-SIGN – hex encoded HMAC SHA-256 of the raw body using the hashed secret.
  • Content-Type: application/json

3. Test with cURL

BODY='{  "projectId": "${PROJECT_ID}",  "order_id": "demo-991",  "amount_minor": 589900,  "addon_selected": true,  "ship_from_city": "Karachi",  "ship_to_city": "Lahore"}'
SECRET_HASH=$(node -e "const c=require('crypto');process.stdout.write(c.createHash('sha256').update(process.env.GC_PROJECT_SECRET).digest('hex'))" GC_PROJECT_SECRET="$GC_PROJECT_SECRET")
SIGNATURE=$(node -e "const c=require('crypto');process.stdout.write(c.createHmac('sha256', Buffer.from(process.env.SECRET_HASH, 'hex')).update(process.env.BODY).digest('hex'))" SECRET_HASH="$SECRET_HASH" BODY="$BODY")

curl -X POST https://greenchain.site/api/record-order   -H "Content-Type: application/json"   -H "X-GC-PUBLIC-KEY: $GC_PUBLIC_KEY"   -H "X-GC-SIGN: $SIGNATURE"   -d "$BODY"

Response: { "receipt_url": "https://greenchain.site/r/abcd1234", "co2_kg": 2.84 }

4. Rotate secrets

Generate a new secret from the dashboard. Update your environment variable, deploy, then pause the previous key. Each rotation is logged in the audit trail with timestamp and actor.

Tip: expose GC_PUBLIC_KEY, GC_PROJECT_SECRET, and GC_SECRET_HASH in your CI so blue/green deploys can warm up without downtime.

How we estimate CO₂

We use a truck-based proxy: co2_kg = (weight_kg × distance_km × 0.1) / 1000. City-to-city averages cover Karachi ↔ Lahore (1210km), Karachi ↔ Islamabad (1410km), Lahore ↔ Islamabad (380km), and 10km for same-city. Everything else defaults to 800km.

Each order stores the factor version so future methodology updates do not change historic receipts. Want to plug in your own distances? Send ship_from_city, ship_to_city, and weight_grams when recording the order.

Rate limiting

60 requests per minute per public key and IP. Exceeding the limit returns 429 with retry_after_ms. Contact us for dedicated ingress if you burst above that.

Error codes

API responses

400
Validation failed. Body did not pass zod schema.
401
Missing or invalid signature / unknown key.
403
Project mismatch for the supplied API key.
429
Rate limit hit (60 requests / minute / IP).
500
Unexpected server error. Retry or contact support.

Need help?

Email hello@greenchain.site or ping us in the merchant Slack. We love pairing on checkout flows.