Skip to content

API reference
every endpoint, explained

Parameters, request examples and responses for every v3 resource, made from the OpenAPI spec.

Base URLhttps://gorest.co.in/public/v3

This is v3, the current version. The v2 reference or the Swagger UI.

Products

Products, carts and orders.

The product object

idstring (uuid)
category_idstring (uuid)
skustring
Your code for the product, unique in your account.
namestring
descriptionstring
price_minorinteger (int64)
The price in minor units of currency: 249900 with INR is ₹2,499.00.
currencystring
An ISO 4217 code (see /currencies). Fixed once the product is made.
stockinteger, or null
Units left; null when stock is not tracked (sample products). An order takes from it and a cancel puts it back.
read_onlyboolean
True for sample data (the seed); it cannot be changed.
created_atstring (date-time)
updated_atstring (date-time)
categoryCategory
A product category. Platform data, the same for everyone. Every field is present unless fields[categories] asks for fewer.
The product object
{
  "id": "0190a8e4-0000-7000-8000-000000000001",
  "category_id": "0190a8e4-0000-7000-8000-000000000001",
  "sku": "EL-1001",
  "name": "Wireless earbuds",
  "description": "Write the tests first.",
  "price_minor": 249900,
  "stock": 40,
  "read_only": false,
  "created_at": "2026-10-31T09:30:00Z",
  "updated_at": "2026-10-31T09:30:00Z"
}

List products

GET/public/v3/products

A token is optional (with products:read): with one you also see your own rows.

Parameters

page[size]query, integeroptional
Items on one page.
page[after]query, stringoptional
The cursor of the next page, from meta.next_cursor or the Link header. Treat it as opaque; it works only with the same query.
page[number]query, integeroptional
Offset paging, 1 based, at most 10,000. Cannot be sent with page[after]. Pages can shift while you write.
page[count]query, booleanoptional
true adds meta.total to a cursor page (it costs a count).
searchquery, stringoptional
Case-insensitive text search over the resource's text fields.
filterquery, objectoptional
filter[category_id]= (one category), filter[currency]=INR (either case). search matches the name, sku and description.
sortquery, created_at | -created_at | name | -name | price_minor | -price_minoroptional
One field; a leading - sorts descending. Default -created_at.
fieldsquery, objectoptional
fields[products]=name,price_minor returns only those fields; included items are added whole.
includequery, stringoptional
Adds related items to each item, one level deep: category. Comma separated.
If-None-Matchheader, stringoptional
An ETag from an earlier answer; an unchanged item answers 304 with no body.
curl -g "https://gorest.co.in/public/v3/products?page[size]=10"
Response 200
{
  "data": [
    {
      "id": "0190a8e4-0000-7000-8000-000000000001",
      "category_id": "0190a8e4-0000-7000-8000-000000000001",
      "sku": "EL-1001",
      "name": "Wireless earbuds",
      "description": "Write the tests first.",
      "price_minor": 249900,
      "stock": 40,
      "read_only": false,
      "created_at": "2026-10-31T09:30:00Z",
      "updated_at": "2026-10-31T09:30:00Z"
    }
  ],
  "meta": {
    "has_more": false,
    "next_cursor": null,
    "total": null
  }
}

Create a product

POST/public/v3/products

Needs a token with products:write.

Parameters

Idempotency-Keyheader, stringoptional
A unique key (a UUID is fine) that makes a POST safe to retry for 24 hours. A retry with the same key, path and body gets the first answer again with Idempotent-Replayed: true and creates nothing; a retry while the first is still running gets 409 conflict with Retry-After: 1. The same key with another request gets 422 idempotency_key_mismatch. Only a 2xx answer is kept, so after an error the retry runs again. An answer over 64 KiB, or one that holds a new token's value, is not kept: its retry gets 409 conflict with the Location of what the first request made.
category_idbody, string (uuid)required
A category (see /categories).
skubody, stringrequired
Your code for the product, unique in your account.
namebody, stringrequired
Not blank; spaces at the ends are dropped.
descriptionbody, stringoptional
price_minorbody, integer (int64)required
currencybody, stringrequired
An ISO 4217 code, either case.
stockbody, integer, or nulloptional
Units in stock; null or left out to not track stock.
curl -X POST "https://gorest.co.in/public/v3/products" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"category_id":"0190a8e4-0000-7000-8000-000000000001","sku":"EL-1001","name":"Wireless earbuds","price_minor":249900,"currency":"INR"}'
Response 201
{
  "id": "0190a8e4-0000-7000-8000-000000000001",
  "category_id": "0190a8e4-0000-7000-8000-000000000001",
  "sku": "EL-1001",
  "name": "Wireless earbuds",
  "description": "Write the tests first.",
  "price_minor": 249900,
  "stock": 40,
  "read_only": false,
  "created_at": "2026-10-31T09:30:00Z",
  "updated_at": "2026-10-31T09:30:00Z"
}

Get a product

GET/public/v3/products/:id

A token is optional (with products:read): with one you also see your own rows.

Parameters

idpath, string (uuid)required
A UUID.
fieldsquery, objectoptional
fields[products]=name,price_minor returns only those fields; included items are added whole.
includequery, stringoptional
Adds related items to each item, one level deep: category. Comma separated.
If-None-Matchheader, stringoptional
An ETag from an earlier answer; an unchanged item answers 304 with no body.
curl "https://gorest.co.in/public/v3/products/0190a8e4-0000-7000-8000-000000000001"
Response 200
{
  "id": "0190a8e4-0000-7000-8000-000000000001",
  "category_id": "0190a8e4-0000-7000-8000-000000000001",
  "sku": "EL-1001",
  "name": "Wireless earbuds",
  "description": "Write the tests first.",
  "price_minor": 249900,
  "stock": 40,
  "read_only": false,
  "created_at": "2026-10-31T09:30:00Z",
  "updated_at": "2026-10-31T09:30:00Z"
}

Change a product (JSON Merge Patch)

PATCH/public/v3/products/:id

Needs a token with products:write.

Parameters

idpath, string (uuid)required
A UUID.
If-Matchheader, stringoptional
The strong ETag the change is based on, from a read without include or from the last write; when the item changed since, the answer is 412. A weak ETag never matches.
Preferheader, return=minimal | return=representationoptional
return=minimal for an answer with no body, return=representation (the default) for the full item (RFC 7240).
category_idbody, string (uuid)optional
skubody, stringoptional
Your code for the product, unique in your account.
namebody, stringoptional
Not blank; spaces at the ends are dropped.
descriptionbody, stringoptional
price_minorbody, integer (int64)optional
A new price; orders already placed keep theirs.
stockbody, integer, or nulloptional
Units in stock, or null to stop tracking.
curl -X PATCH "https://gorest.co.in/public/v3/products/0190a8e4-0000-7000-8000-000000000001" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"category_id":"0190a8e4-0000-7000-8000-000000000001"}'
Response 200
{
  "id": "0190a8e4-0000-7000-8000-000000000001",
  "category_id": "0190a8e4-0000-7000-8000-000000000001",
  "sku": "EL-1001",
  "name": "Wireless earbuds",
  "description": "Write the tests first.",
  "price_minor": 249900,
  "stock": 40,
  "read_only": false,
  "created_at": "2026-10-31T09:30:00Z",
  "updated_at": "2026-10-31T09:30:00Z"
}

Delete a product

DELETE/public/v3/products/:id

Needs a token with products:write.

Parameters

idpath, string (uuid)required
A UUID.
If-Matchheader, stringoptional
The strong ETag the change is based on, from a read without include or from the last write; when the item changed since, the answer is 412. A weak ETag never matches.
curl -X DELETE "https://gorest.co.in/public/v3/products/0190a8e4-0000-7000-8000-000000000001" \
  -H "Authorization: Bearer YOUR_TOKEN"
Response 204
(empty body)

Authentication

Most reads need no token: you see the read only sample data. With a token you also see your own rows. Writes, and the access tokens, my data and change stream calls, need a token with the scope the call names, such as users:write. Make a token on the tokens page after you log in.

Authorization: Bearer YOUR_TOKEN
The only way to send a token in v3. A token never goes in the URL.

No token or a wrong one gives 401 with WWW-Authenticate. A token without the scope gives 403 with error="insufficient_scope". Sample rows (read_only: true) cannot be changed.

Make a token

Pagination

A list answers {"data": [...], "meta": {...}}, 25 items by default. Set page[size] from 1 to 100. For the next page send page[after] with meta.next_cursor; the same link is in the Link header.

meta.has_more
true when there is a next page.
meta.next_cursor
Send it as page[after] for the next page; null on the last one.
meta.total
Only with page[count]=true, or with page[number].
page[number]
Offset paging from 1 to 10,000, in place of page[after].
Link
rel="next", "prev", "first" and, for offset paging, "last" (RFC 8288).

Rate limits

Every answer carries the IETF rate limit fields. A token has its own limit, 300 calls a minute by default (1 to 600, set on the tokens page). With no token, an IP gets 120 calls a minute. Past the limit you get 429 with Retry-After.

RateLimit-Policy
The limit and its window, for example "token";q=300;w=60.
RateLimit
Calls left and the seconds until the window resets.
Retry-After
On a 429: the seconds to wait.

Errors and status codes

200 OK
The item or the list is in the body.
201 Created
The new item is in the body, and Location has its URL.
204 No Content
A delete worked. The body is empty.
304 Not Modified
Your copy (If-None-Match with the ETag) is still good.
400 Bad Request
A parameter is wrong, unknown or out of range.
401 Unauthorized
No token, or it is wrong, expired or revoked.
403 Forbidden
The token lacks the scope, or the row is sample data.
404 Not Found
No such item, or you cannot see it.
409 Conflict
A duplicate, or the same Idempotency-Key is busy.
412 Precondition Failed
If-Match did not match: someone changed the item.
422 Unprocessable
A field failed a check. errors has a pointer and a code for each.
429 Too Many Requests
The rate limit is used up; wait Retry-After seconds.
500 Server Error
A fault on our side. Send the request_id when you report it.
A 422 body 422Every error code
{
  "type": "https://www.gorest.co.in/docs/api/errors#validation_failed",
  "title": "Unprocessable Content",
  "status": 422,
  "code": "validation_failed",
  "detail": "Some fields are not valid.",
  "instance": "/public/v3/users",
  "request_id": "0190a8e4-0000-7000-8000-0000000000aa",
  "errors": [
    { "pointer": "/email", "code": "taken", "detail": "has already been taken" }
  ]
}

Format and testing

/http/status/503
Answers with that status, with the headers a real one carries. Any code from 200 to 599.
/http/delay/1500
Waits that many milliseconds, up to 10,000, then answers.
ETag and If-Match
Send If-Match on PATCH or DELETE so you never overwrite a newer change (412 if it changed).
Idempotency-Key
A header on POST that makes a retry safe: the same answer for 24 hours.
fields, include, sort
fields[users]=id,name returns fewer fields; include=user embeds the related item; sort=-created_at orders a list.

Want to try a call now? Open the REST console.