Sandbox · simulated data

For agent developers

OrderForge has a small public interface so another program, such as a buyer's assistant, can ask a demo shop for a priced box and read the answer.

The agent can request and read; it cannot accept or pay.

It sends five facts. Code, not a model, picks the box and prices it. A person opens the link it gets back, chooses the box, accepts the exact price and approves the payment on PayPal's own page. The shop then decides.

What an agent may send

Exactly these five fields. Anything else is refused: a price, a total, a discount, a product choice or free text has nowhere to go. The table is generated from the schema the route uses.

FieldTypeNeededRangeMeaning
boxCountintegeryes1 to 10000How many boxes.
noFoodbooleanyesnoneTrue if the order must contain no food.
logoRequiredbooleanyesnoneTrue if the customer's logo must be on the order.
maxPricePerBoxMinorintegeryes1 to 10000000The most the customer will pay per box, in cents (USD).
requestedPickupDatestring, YYYY-MM-DDoptionalnoneThe earliest pickup day wanted.

Make a request

One call. No key is needed on the sandbox demo.

curl -X POST https://order-forge.afras.dev/api/agent/v1/stores/demo-gift-boxes/requests \
  -H "Content-Type: application/json" \
  -d '{"boxCount":20,"noFood":true,"logoRequired":true,"maxPricePerBoxMinor":4000}'

What comes back

Produced by the real handler and the real pricing engine, on the demo shop's seed data. Every amount is whole cents. The id and the two tokens are placeholders.

For 20 boxes, code priced $35.00 a box and $700.00 in total, shown below as 3500 and 70000 cents.

{
  "request": {
    "id": "11111111-2222-4333-8444-555555555555",
    "status": "CONFIGURING",
    "proposalStatus": "VALID",
    "proposals": [
      {
        "kind": "BOX",
        "lines": [
          { "slotId": "notebook", "sku": "NOTEBOOK-A5", "name": "A5 notebook", "unitPriceMinor": 1200, "quantity": 1 },
          { "slotId": "pen", "sku": "PEN-BLK", "name": "Black gel pen", "unitPriceMinor": 300, "quantity": 1 },
          { "slotId": "gift", "sku": "BOTTLE-STEEL", "name": "Steel water bottle", "unitPriceMinor": 1300, "quantity": 1 },
          { "slotId": "card", "sku": "CARD-BRANDED", "name": "Branded welcome card", "unitPriceMinor": 200, "quantity": 1 },
          { "slotId": "packaging", "sku": "PACK-BOX", "name": "Gift box packaging", "unitPriceMinor": 500, "quantity": 1 }
        ],
        "perBoxMinor": 3500,
        "totalMinor": 70000,
        "boxCount": 20,
        "currency": "USD"
      }
    ],
    "blockers": []
  },
  "humanUrl": "https://order-forge.afras.dev/o/example-human-token",
  "requestToken": "example-agent-token",
  "note": "Send requestToken as 'Authorization: Bearer <token>' to GET /api/agent/v1/requests/{id}. Give humanUrl to a person: only they can choose the box, accept the price and pay."
}

Read it back

The response includes a read-only token. Send it as a bearer token to read the same request later. It cannot read any other request.

curl https://order-forge.afras.dev/api/agent/v1/requests/<request id> \
  -H "Authorization: Bearer <requestToken>"

When the box cannot be made

A request that does not fit the shop's stock gets a coded reason and the options code found, not a guess. Here the steel bottle runs out, so the engine offers one valid swap.

For 30 boxes the swap is priced at $36.00 a box and $1,080.00 in total.

{
  "request": {
    "id": "11111111-2222-4333-8444-555555555555",
    "status": "CONFIGURING",
    "proposalStatus": "BLOCKED",
    "proposals": [
      {
        "kind": "SWAP",
        "lines": [
          { "slotId": "notebook", "sku": "NOTEBOOK-A5", "name": "A5 notebook", "unitPriceMinor": 1200, "quantity": 1 },
          { "slotId": "pen", "sku": "PEN-BLK", "name": "Black gel pen", "unitPriceMinor": 300, "quantity": 1 },
          { "slotId": "gift", "sku": "ORGANIZER-DESK", "name": "Desk organizer", "unitPriceMinor": 1400, "quantity": 1 },
          { "slotId": "card", "sku": "CARD-BRANDED", "name": "Branded welcome card", "unitPriceMinor": 200, "quantity": 1 },
          { "slotId": "packaging", "sku": "PACK-BOX", "name": "Gift box packaging", "unitPriceMinor": 500, "quantity": 1 }
        ],
        "perBoxMinor": 3600,
        "totalMinor": 108000,
        "boxCount": 30,
        "currency": "USD",
        "swap": { "slotId": "gift", "fromSku": "BOTTLE-STEEL", "toSku": "ORGANIZER-DESK" }
      }
    ],
    "blockers": [
      { "code": "INSUFFICIENT_STOCK", "sku": "BOTTLE-STEEL", "needed": 30, "available": 24 }
    ]
  },
  "humanUrl": "https://order-forge.afras.dev/o/example-human-token",
  "requestToken": "example-agent-token",
  "note": "Send requestToken as 'Authorization: Bearer <token>' to GET /api/agent/v1/requests/{id}. Give humanUrl to a person: only they can choose the box, accept the price and pay."
}

Who does what

  1. The agent. Posts the five fields.
  2. Code. Chooses a box from the shop's own list and prices it to the cent.
  3. A person. Opens the link, chooses the box and accepts the exact price.
  4. PayPal. The person approves; PayPal sets the money aside. Nothing is charged yet.
  5. The shop. Accepts, and the money is charged, or declines, and it is released.

What the agent cannot do

  • Set or change a price.
  • Choose the products in the box.
  • Accept a quote.
  • Approve or make a payment.
  • Read any request but its own.

Reference and limits

OpenAPI description (JSON)

These brakes slow abuse. They are not a quota, and they are counted per server instance.

Requests one address may create
10 a minute
Requests all addresses may create for one shop
60 a minute
Reads and browsing, per address
60 a minute
Requests one shop takes through this interface
200 in 24 hours