Bids

Place bids on inventory programmatically and read your team's bids. Placing a bid requires the bids.write scope and a token bound to a team via Login with MGX. Reading uses bids.read.

The counterparty (seller) on a bid stays null until both invoices on the resulting trade are paid.

POST/v1/inventory/:id/bids

Place a bid

Place a bid on a listing. MGX runs the same credit, payment, and eligibility rules as the web app. Pass an Idempotency-Key header to make retries safe.

Body

  • Name
    price
    Type
    object
    Description
    amount in MT — for graded listings.
  • Name
    bids
    Type
    array
    Description
    [ grade, price ] — for ungraded (multi-grade) listings.
  • Name
    quantity_mt
    Type
    number
    Description
    Quantity in tonnes (required).
  • Name
    delivery
    Type
    object
    Description
    from, to ISO dates (required).
  • Name
    fob_farm
    Type
    boolean
    Description
    Defaults true.
  • Name
    delivery_location_id
    Type
    integer
    Description
    Required when not FOB.
  • Name
    subject_to_sample_approval
    Type
    boolean
    Description
  • Name
    additional_terms
    Type
    string
    Description
    Free text (moderated).
  • Name
    expires_at
    Type
    string
    Description
    ISO datetime; defaults to +7 days.

Request

POST
/v1/inventory/inv_3Kd9aZ/bids
curl https://api.mygrainexchange.com/v1/inventory/inv_3Kd9aZ/bids \
  -H "Authorization: Bearer {token}" \
  -H "Idempotency-Key: 7f1c..." \
  -H "Content-Type: application/json" \
  -d '{
    "price": { "amount": 308.00, "unit": "MT" },
    "quantity_mt": 86.0,
    "delivery": { "from": "2026-08-15", "to": "2026-09-15" },
    "fob_farm": true
  }'

Response

{
  "data": {
    "id": "bid_7Qp2",
    "reference": "BID-10482",
    "inventory_id": "inv_3Kd9aZ",
    "status": "pending",
    "price": { "amount": 308.0, "currency": "CAD", "unit": "MT" },
    "quantity_mt": 86.0,
    "counterparty": null
  }
}

GET/v1/bids

List your bids

Bids placed by your team. Filter with status (pending, accepted, rejected, countered, expired). Poll this to discover lifecycle changes (e.g. a lot delisting).

Request

GET
/v1/bids
curl https://api.mygrainexchange.com/v1/bids?status=pending \
  -H "Authorization: Bearer {token}"

GET/v1/bids/:id

Get a bid

Retrieve one of your team's bids by id. Returns 404 if it does not belong to your team.

Request

GET
/v1/bids/bid_7Qp2
curl https://api.mygrainexchange.com/v1/bids/bid_7Qp2 \
  -H "Authorization: Bearer {token}"

Respond to a counter-offer

When a seller counters your bid (the bid.countered webhook), respond with one of:

POST/v1/bids/:id/accept

Accept

Accept the counter. This creates a trade and invoices. 404 if the bid is not your team's, 422 if it is not pending.

Request

POST
/v1/bids/bid_7Qp2/accept
curl -X POST https://api.mygrainexchange.com/v1/bids/bid_7Qp2/accept \
  -H "Authorization: Bearer {token}"
POST/v1/bids/:id/reject

Reject

Decline the counter.

Request

POST
/v1/bids/bid_7Qp2/reject
curl -X POST https://api.mygrainexchange.com/v1/bids/bid_7Qp2/reject \
  -H "Authorization: Bearer {token}"
POST/v1/bids/:id/counter

Counter back

Send your own counter. Same body shape as placing a bid (price, quantity, delivery).

Request

POST
/v1/bids/bid_7Qp2/counter
curl -X POST https://api.mygrainexchange.com/v1/bids/bid_7Qp2/counter \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{ "price": { "amount": 305.0, "unit": "MT" }, "quantity_mt": 86.0, "delivery": { "from": "2026-08-15", "to": "2026-09-15" }, "expires_at": "2026-06-25T17:00:00Z" }'

GET/v1/delivery-locations

List your delivery locations

Elevators bidding for delivered grain (not FOB farm) must name one of their own delivery locations. List them here, then pass the integer id as delivery_location_id when placing the bid. FOB-farm bids need no location.

Request

GET
/v1/delivery-locations
curl https://api.mygrainexchange.com/v1/delivery-locations \
  -H "Authorization: Bearer {token}"

Was this page helpful?