Developers 12 min read

Send orders from your custom-built website to eGrow (API guide for developers and AI coding tools)

Hand-coded site, Next.js, Laravel, or built with Claude, Codex, Cursor, Lovable or Bolt? One API call at checkout sends every order into eGrow, which then confirms, ships, tracks and follows up for you. Why it pays off, the exact orderFullCreate request with field reference, copy-paste examples in cURL, Node.js, PHP and Python, safe updates with orderCreateOrUpdate, troubleshooting β€” and a ready-made prompt to paste into your AI coder.

Built your own website β€” hand-coded, or with an AI coding tool like Claude, Codex, Cursor, Lovable or Bolt? You don't need Shopify or WooCommerce to use eGrow. One API call at checkout sends every order into eGrow, and from that second eGrow confirms it, ships it, tracks it and follows up with the customer for you. This guide shows exactly how, with copy-paste code and a ready-made prompt for your AI coder.

Why send your orders to eGrow

A custom website is great at taking orders. It is not built to run everything that happens after the order β€” and for cash-on-delivery that "after" is where the money is won or lost. Once an order reaches eGrow:

  • Confirmation happens by itself β€” WhatsApp confirmation, the AI agent, or your call centre, with the customer's answers written back on the order.
  • Shipping is one click (or zero) β€” the parcel is created at your delivery company and the tracking number is saved on the order; statuses sync back automatically.
  • Customers are kept informed β€” "order received", "on its way", "delivery failed, can we retry?" messages go out from your WhatsApp number without you touching anything.
  • Returns go down β€” addresses and cities are validated, duplicates are flagged, unreachable customers are followed up, and abandoned checkouts can be recovered.
  • You see the real numbers β€” confirmation rate, delivery rate, returns, revenue by product and by campaign (UTM), all in one place.

Your website stays your website. eGrow is the operations engine behind it.

How it works

  1. You create a Personal API Key in eGrow (2 minutes).
  2. When a customer places an order on your site, your server sends that order to the eGrow API (orderFullCreate).
  3. eGrow answers with the order id β€” and takes it from there.

That's the whole integration. Everything below is detail.

Before you begin

  • An eGrow account with at least one pipeline (the default one is fine).
  • A website where you control the checkout code, or an AI coding tool that can edit it for you.
  • A Personal API Key from Settings β†’ Developer β†’ API Key.

Important: your API key gives full access to your account. Call the eGrow API from your server (your backend, a serverless function, a Next.js route handler, a Laravel controller…), never from the browser, and never commit the key to Git. Store it as an environment variable, e.g. EGROW_API_KEY.

Step 1: Get your API key

  1. In eGrow, open Settings β†’ Developer β†’ API Key.
  2. Click Generate and copy the key (it starts with egrow_).
  3. Save it in your project's environment as EGROW_API_KEY.

Step 2: Send the order

The eGrow API is GraphQL. You always send a POST to the same endpoint with a JSON body that contains a query and its variables.

  • Endpoint: https://api5.egrow.com/graphql
  • Headers: Authorization: Bearer YOUR_API_KEY and Content-Type: application/json
  • Mutation: orderFullCreate β€” creates a complete order (customer, address, products, prices) in one call.

The mutation

mutation CreateOrder($input: OrderFullCreateInput!) {
 orderFullCreate(input: $input) {
 order { id orderNumber }
 userErrors { field message code }
 }
}

The variables (a real COD order)

{
 "input": {
 "orderExternalId": "WEB-10245",
 "orderNumber": "10245",
 "orderType": "Order",
 "paymentMethod": "COD",
 "financialStatus": "Pending",
 "currency": "MAD",
 "phone": "+212612345678",
 "email": "[email protected]",
 "customer": {
 "firstName": "Amina",
 "lastName": "El Idrissi",
 "phone": "+212612345678",
 "email": "[email protected]"
 },
 "shippingAddress": {
 "firstName": "Amina",
 "lastName": "El Idrissi",
 "phone": "+212612345678",
 "address1": "12 Rue Al Massira, Apt 4",
 "city": "Casablanca",
 "province": "Casablanca-Settat",
 "countryCode": "MA"
 },
 "lineItems": [
 {
 "title": "Leather wallet β€” brown",
 "sku": "WAL-BR-01",
 "externalProductId": "prod_88",
 "quantity": 2,
 "price": 149.00,
 "imageUrl": "https://yourshop.ma/img/wallet-brown.jpg"
 }
 ],
 "subtotal": 298.00,
 "shippingPrice": 30.00,
 "note": "Customer prefers delivery after 6pm",
 "tags": ["website"],
 "utmParameters": { "source": "facebook", "campaign": "ramadan-2026" }
 }
}

What each field is for

FieldWhat to send
orderExternalIdYour own order id. Always send it β€” it lets eGrow recognise the same order if you send it twice, and lets you update it later.
orderNumberThe number the customer sees (optional β€” eGrow generates one if empty).
customerfirstName, lastName, phone, email. The phone is what WhatsApp confirmation uses β€” send it in international format (+212…).
shippingAddressaddress1, city, province, countryCode (+ name and phone). The city is what your delivery company needs, so send it exactly as the customer chose it.
lineItemsOne entry per product: title, quantity, price (unit price), and ideally sku / externalProductId so eGrow can match your catalogue and count stock.
subtotal, shippingPriceNumbers, in the order's currency.
paymentMethod, financialStatus"COD" + "Pending" for cash on delivery; "Paid" if the customer paid online.
orderType"Order" for a normal order, "AbandonedCart" to push an abandoned checkout so eGrow can recover it (add abandonedCheckoutUrl).
note, tags, utmParametersOptional. Notes show to your agents; tags help you filter; UTM parameters give you revenue per campaign.
pipelineId, storeIdOptional. Leave them out to use your defaults; set them if you run several pipelines or stores.

The response

{
 "data": {
 "orderFullCreate": {
 "order": { "id": 1834512, "orderNumber": "10245" },
 "userErrors": []
 }
 }
}

Save order.id next to your own order. If userErrors is not empty, nothing was created β€” the message tells you which field to fix.

Step 3: Code examples

Every example does the same thing: build the variables from your checkout data and POST them. Replace the key with your environment variable.

cURL (test it from your terminal)

curl -X POST https://api5.egrow.com/graphql \
 -H "Authorization: Bearer $EGROW_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{
 "query": "mutation CreateOrder($input: OrderFullCreateInput!) { orderFullCreate(input: $input) { order { id orderNumber } userErrors { field message code } } }",
 "variables": { "input": { "orderExternalId": "WEB-10245", "paymentMethod": "COD", "currency": "MAD",
 "customer": { "firstName": "Amina", "lastName": "El Idrissi", "phone": "+212612345678" },
 "shippingAddress": { "address1": "12 Rue Al Massira", "city": "Casablanca", "countryCode": "MA", "phone": "+212612345678" },
 "lineItems": [ { "title": "Leather wallet β€” brown", "sku": "WAL-BR-01", "quantity": 2, "price": 149 } ],
 "subtotal": 298, "shippingPrice": 30 } }
 }'

Node.js / Next.js (route handler or API route)

// app/api/checkout/route.js β€” runs on the server, the key never reaches the browser
const MUTATION = `mutation CreateOrder($input: OrderFullCreateInput!) {
 orderFullCreate(input: $input) { order { id orderNumber } userErrors { field message code } }
}`;

export async function sendOrderToEgrow(order) {
 const input = {
 orderExternalId: String(order.id),
 orderNumber: String(order.number),
 orderType: "Order",
 paymentMethod: order.paidOnline ? "CARD" : "COD",
 financialStatus: order.paidOnline ? "Paid" : "Pending",
 currency: "MAD",
 phone: order.customer.phone,
 email: order.customer.email,
 customer: { firstName: order.customer.firstName, lastName: order.customer.lastName,
 phone: order.customer.phone, email: order.customer.email },
 shippingAddress: { firstName: order.customer.firstName, lastName: order.customer.lastName,
 phone: order.customer.phone, address1: order.address.line1,
 city: order.address.city, province: order.address.region, countryCode: "MA" },
 lineItems: order.items.map(i => ({ title: i.name, sku: i.sku, externalProductId: String(i.productId),
 quantity: i.qty, price: i.unitPrice, imageUrl: i.image })),
 subtotal: order.subtotal,
 shippingPrice: order.shipping,
 note: order.note || undefined,
 tags: ["website"],
 utmParameters: order.utm || undefined,
 };

 const res = await fetch("https://api5.egrow.com/graphql", {
 method: "POST",
 headers: { "Authorization": `Bearer ${process.env.EGROW_API_KEY}`, "Content-Type": "application/json" },
 body: JSON.stringify({ query: MUTATION, variables: { input } }),
 });
 const json = await res.json();
 const result = json.data?.orderFullCreate;
 if (!result || result.userErrors?.length) {
 throw new Error("eGrow rejected the order: " + JSON.stringify(result?.userErrors ?? json.errors));
 }
 return result.order; // { id, orderNumber } β€” store it with your order
}

PHP (Laravel, WordPress, plain PHP)

function sendOrderToEgrow(array $order): array {
 $mutation = 'mutation CreateOrder($input: OrderFullCreateInput!) {
 orderFullCreate(input: $input) { order { id orderNumber } userErrors { field message code } }
 }';
 $input = [
 'orderExternalId' => (string)$order['id'],
 'paymentMethod' => 'COD',
 'financialStatus' => 'Pending',
 'currency' => 'MAD',
 'phone' => $order['phone'],
 'customer' => ['firstName' => $order['first_name'], 'lastName' => $order['last_name'], 'phone' => $order['phone']],
 'shippingAddress' => ['address1' => $order['address'], 'city' => $order['city'], 'countryCode' => 'MA', 'phone' => $order['phone']],
 'lineItems' => array_map(fn($i) => ['title' => $i['name'], 'sku' => $i['sku'], 'quantity' => (int)$i['qty'], 'price' => (float)$i['price']], $order['items']),
 'subtotal' => (float)$order['subtotal'],
 'shippingPrice' => (float)$order['shipping'],
 ];
 $ch = curl_init('https://api5.egrow.com/graphql');
 curl_setopt_array($ch, [
 CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 20,
 CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('EGROW_API_KEY'), 'Content-Type: application/json'],
 CURLOPT_POSTFIELDS => json_encode(['query' => $mutation, 'variables' => ['input' => $input]]),
 ]);
 $json = json_decode((string)curl_exec($ch), true);
 curl_close($ch);
 $result = $json['data']['orderFullCreate'] ?? null;
 if (!$result || !empty($result['userErrors'])) {
 throw new RuntimeException('eGrow rejected the order: ' . json_encode($result['userErrors'] ?? $json['errors'] ?? null));
 }
 return $result['order']; // ['id' => …, 'orderNumber' => …]
}

Python (Django, FastAPI, Flask)

import os, requests

MUTATION = """mutation CreateOrder($input: OrderFullCreateInput!) {
 orderFullCreate(input: $input) { order { id orderNumber } userErrors { field message code } }
}"""

def send_order_to_egrow(order):
 payload = {
 "orderExternalId": str(order["id"]),
 "paymentMethod": "COD", "financialStatus": "Pending", "currency": "MAD",
 "phone": order["phone"],
 "customer": {"firstName": order["first_name"], "lastName": order["last_name"], "phone": order["phone"]},
 "shippingAddress": {"address1": order["address"], "city": order["city"], "countryCode": "MA", "phone": order["phone"]},
 "lineItems": [{"title": i["name"], "sku": i["sku"], "quantity": i["qty"], "price": i["price"]} for i in order["items"]],
 "subtotal": order["subtotal"], "shippingPrice": order["shipping"],
 }
 r = requests.post("https://api5.egrow.com/graphql",
 headers={"Authorization": f"Bearer {os.environ['EGROW_API_KEY']}", "Content-Type": "application/json"},
 json={"query": MUTATION, "variables": {"input": payload}}, timeout=20)
 result = r.json().get("data", {}).get("orderFullCreate")
 if not result or result.get("userErrors"):
 raise RuntimeError(f"eGrow rejected the order: {result and result.get('userErrors')}")
 return result["order"] # {"id": …, "orderNumber": …}

Tip: send the order to eGrow after you have saved it on your side, and do it in a background job or right after the "thank you" page renders, so a slow network never blocks your customer. If the call fails, retry later with the same orderExternalId.

Updating an order you already sent

Customer changed the address, or you cancelled the order on your site? Use orderCreateOrUpdate with the same orderExternalId β€” it takes exactly the same input, and eGrow updates the existing order instead of creating a second one. This is also the safest choice if you are not sure whether an order was already sent.

mutation UpsertOrder($input: OrderCreateOrUpdateInput!) {
 orderCreateOrUpdate(input: $input) {
 order { id orderNumber }
 userErrors { field message code }
 }
}

Test it before you write code

The API Playground (Settings β†’ Developer β†’ Playground) has an Add order action that builds this exact request from a form, runs it, and shows the live response. Click Fill dummy data, run it, and you will see a new order appear in your orders list. Then copy the cURL it generated β€” it is the same call as above, with your account's real ids for pipeline and store.

Warning: the Playground and the API both act on your real account. Use your own phone number as the test customer, and delete the test orders afterwards.

Let your AI coder do it: a prompt you can paste

If your site was built with Claude, Codex, Cursor, Lovable, Bolt or a similar tool, you don't have to write any of this yourself. Paste the prompt below into the same tool, inside your project: the assistant is already in your code, so it will find the checkout, follow your stack and conventions, and add the integration. Nothing to fill in.

Integrate this project's checkout with eGrow so every new order is sent to eGrow through its API.
You are already in the codebase: find where an order is saved, use the language, framework and
conventions this project already has, and reuse my existing order/customer/product objects.

1. Add a server-side function (e.g. sendOrderToEgrow) that POSTs JSON to https://api5.egrow.com/graphql
 with headers Authorization: Bearer <EGROW_API_KEY> and Content-Type: application/json.
 Read the key from an environment variable named EGROW_API_KEY. It must never reach the browser.
2. Send this GraphQL mutation:
 mutation CreateOrder($input: OrderFullCreateInput!) {
 orderFullCreate(input: $input) { order { id orderNumber } userErrors { field message code } }
 }
 and map my order into `input` like this:
 orderExternalId = my order id (always), orderNumber, orderType "Order",
 paymentMethod "COD" + financialStatus "Pending" (or "Paid" when paid online), currency "MAD",
 phone, email, customer {firstName,lastName,phone,email},
 shippingAddress {firstName,lastName,phone,address1,city,province,countryCode "MA"},
 lineItems [{title,sku,externalProductId,quantity,price (unit price),imageUrl}],
 subtotal, shippingPrice, note, tags ["website"], utmParameters {source,medium,campaign,content,term}.
 Phone numbers must be in international format (+212…). Leave out fields I don't have.
3. Call it right after the order is saved, without blocking the customer's confirmation page
 (background job, queue, or after the response is sent). On failure log the error and retry
 later with the same orderExternalId β€” never create the same order twice.
4. Store the returned order.id and orderNumber on my order record (add a field if needed).
5. Treat a non-empty userErrors as a failure and include its messages in the log.
6. Add a small script or test that sends one sample order and prints the response.
Show me the diff, then run the test.

Tip: if your AI tool supports MCP (Claude Code, Cursor and others do), connect it to eGrow's MCP server under Settings β†’ Developer β†’ MCP. The agent can then check its own work: "did the test order arrive in eGrow?" β€” and you can ask it things like "how many orders were delivered this week?" from the same chat.

Prompt for updates and cancellations

Extend the eGrow integration: when an order is edited or cancelled on my site, send it again with
the mutation orderCreateOrUpdate (input type OrderCreateOrUpdateInput, same fields as before,
same orderExternalId) so eGrow updates the existing order instead of creating a new one.

Troubleshooting

What you seeWhat it means
401 UnauthorizedThe key is missing, wrong, or was regenerated. Check the Authorization: Bearer … header and the environment variable on the server that makes the call.
403 ForbiddenThe request was blocked before reaching the API β€” usually a missing User-Agent header or a client that sends the body as form data. Send JSON with Content-Type: application/json.
userErrors is not emptyA field is invalid. The field tells you which one β€” most often a phone that is not in international format, an empty city, or a line item without a title or quantity.
The order was created twiceYou retried without orderExternalId, or used orderFullCreate for an update. Always send orderExternalId, and use orderCreateOrUpdate for retries and edits.
Confirmation messages are not going outThe order arrived, but automation runs on the pipeline it landed in. Check the order's pipeline and stage in eGrow, and that your WhatsApp number is connected.
Products don't match your catalogueSend the same sku or externalProductId you use in eGrow's products, so stock and reports line up.

What's next

  • Connect your delivery company under Integrations, and switch on the automation that creates the parcel as soon as an order is confirmed.
  • Turn on order auto-confirmation via WhatsApp so new orders are confirmed while you sleep.
  • Push abandoned checkouts with orderType: "AbandonedCart" and let eGrow recover them.
  • Explore the rest of the API β€” customers, products, pipelines β€” in the Playground.

Was this article helpful?

Next

How to Integrate TikTok Shop with eGrow πŸ›οΈ

Related Articles

Can't find what you're looking for?

Our support team is here to help. Submit a ticket and we'll get back to you as soon as possible.

Contact Support
Need Help?