{
  "openapi": "3.1.0",
  "info": {
    "title": "GRAJ Protocol API",
    "version": "v1 (protocol 2026.09)",
    "description": "The versioned GRAJ API. Most doors read. The doors that write — POST /agent-tools, POST and PATCH /products, POST /fulfilments — need a key with the write scope, only ever act as the key owner, go through the same rules as the screens, and accept an Idempotency-Key header so a retried write happens once. None places an order or moves money. Keys are the participant's own, issued at /settings/api-keys: shown once, stored as a hash, scoped (read, write, admin), revocable, optionally limited to named addresses, 600 requests a minute. Doors marked Public need no key: agents, flags, health, protocol, roadmap.",
    "contact": {
      "name": "GRAJ",
      "url": "https://www.getreadyandjump.com/developer"
    }
  },
  "servers": [
    {
      "url": "https://www.getreadyandjump.com/api/v1"
    }
  ],
  "externalDocs": {
    "description": "Developer docs",
    "url": "https://www.getreadyandjump.com/docs"
  },
  "security": [
    {
      "apiKey": []
    },
    {
      "bearer": []
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "graj_live_… from /settings/api-keys"
      },
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Authorization: Bearer graj_live_… (the same key)"
      }
    }
  },
  "tags": [
    {
      "name": "Public",
      "description": "No key needed."
    },
    {
      "name": "Your key",
      "description": "Needs your own API key; answers about you, or public directory data."
    }
  ],
  "paths": {
    "/agent-tools": {
      "get": {
        "operationId": "get_agent_tools",
        "summary": "The tools your own agent can run",
        "description": "The tools the key owner's agent has for their real role, each with its input schema and the scope it needs (read or write). No model is called and nothing is billed. Read-only.",
        "tags": [
          "Your key"
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {},
                    "role": {},
                    "key": {},
                    "count": {
                      "type": "integer"
                    },
                    "tools": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {},
                          "description": {},
                          "input_schema": {},
                          "scope": {}
                        }
                      }
                    },
                    "usage": {},
                    "billed": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      },
      "post": {
        "operationId": "post_agent_tools",
        "summary": "Run one of your agent's tools",
        "description": "Runs one tool as the key owner and nobody else, through the same executor the agent uses in chat. A tool that reads needs the read scope; one that writes (a line sheet, an expansion plan, a press or production draft, or claiming, confirming or assigning a delivery run, which tells the people on the run) needs a key with the write scope. No model is called; no order is placed and no money moves.",
        "tags": [
          "Your key"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tool"
                ],
                "properties": {
                  "tool": {
                    "type": "string",
                    "description": "A tool name from GET /api/v1/agent-tools."
                  },
                  "input": {
                    "type": "object",
                    "description": "The tool's input, matching its input_schema."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {},
                    "tool": {},
                    "role": {},
                    "message": {},
                    "data": {}
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/agents": {
      "get": {
        "operationId": "get_agents",
        "summary": "The twelve GRAJ agents",
        "description": "Name, role, whether each is live, and what it does. All twelve are AI agents; people talk to them at /chat with a GRAJ account. Read-only.",
        "tags": [
          "Public"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "agents": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {},
                          "role": {},
                          "endpoint": {},
                          "live": {},
                          "desc": {}
                        }
                      }
                    },
                    "count": {
                      "type": "integer"
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "model": {},
                    "usage": {}
                  }
                }
              }
            }
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/agreements": {
      "get": {
        "operationId": "get_agreements",
        "summary": "Your seller agreements",
        "description": "Commission agreements the key owner is a party to, as the brand or the seller. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Only agreements with this status.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "active",
                "declined",
                "ended"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "The whole stored row, every column the table has."
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/analytics": {
      "get": {
        "operationId": "get_analytics",
        "summary": "Your own numbers",
        "description": "The key owner's own GMV (net of discounts), fees and commissions on delivered orders, orders by status and events by type. Never protocol-wide. Read-only.",
        "tags": [
          "Your key"
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "gmv_cents": {
                      "type": "integer",
                      "description": "Cents (minor units of the currency)."
                    },
                    "gmv": {},
                    "fees_cents": {
                      "type": "integer",
                      "description": "Cents (minor units of the currency)."
                    },
                    "fees": {},
                    "commissions_cents": {
                      "type": "integer",
                      "description": "Cents (minor units of the currency)."
                    },
                    "commissions": {},
                    "orders_by_status": {},
                    "events_by_type": {},
                    "total_orders": {},
                    "version": {
                      "type": "string",
                      "const": "v1"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/brands": {
      "get": {
        "operationId": "get_brands",
        "summary": "Brand directory",
        "description": "Public profiles of active brands (test and verification accounts excluded): name, handle, place, bio, logo and contribution score. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Only participants in this country (exact match on the profile's country, up to 60 characters).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {},
                          "handle": {},
                          "primary_role": {},
                          "country": {},
                          "state": {},
                          "city": {},
                          "bio": {},
                          "logo_url": {},
                          "contribution_score": {},
                          "contribution_tier": {}
                        }
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/catalog": {
      "get": {
        "operationId": "get_catalog",
        "summary": "Active products across GRAJ, with the brand",
        "description": "Active products from every brand, with brand name and handle. Prices are in cents. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "brand_id",
            "in": "query",
            "required": false,
            "description": "Only this brand's rows. Ignored if it is not a uuid.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Category contains this text (case-insensitive, up to 80 characters).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_price",
            "in": "query",
            "required": false,
            "description": "Wholesale price at least this many cents.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "max_price",
            "in": "query",
            "required": false,
            "description": "Wholesale price at most this many cents.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {},
                          "sku": {},
                          "brand_id": {
                            "type": "string"
                          },
                          "category": {},
                          "description": {},
                          "images": {},
                          "wholesale_price_cents": {
                            "type": "integer",
                            "description": "Cents (minor units of the currency)."
                          },
                          "suggested_retail_cents": {
                            "type": "integer",
                            "description": "Cents (minor units of the currency)."
                          },
                          "currency_code": {},
                          "minimum_order_qty": {},
                          "minimum_order_value_cents": {
                            "type": "integer",
                            "description": "Cents (minor units of the currency)."
                          },
                          "units_per_case": {},
                          "unit": {},
                          "lead_time_days": {},
                          "status": {},
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "operators": {}
                        }
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/coselling": {
      "get": {
        "operationId": "get_coselling",
        "summary": "Your co-selling partnerships",
        "description": "Co-sell partnerships the key owner is in, as the primary or the partner seller. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "The whole stored row, every column the table has."
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/credits": {
      "get": {
        "operationId": "get_credits",
        "summary": "Your GRAJ Credits balance and ledger",
        "description": "The key owner's credit balance (cents and dollars) and their ledger, newest first. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "balance_cents": {
                      "type": "integer",
                      "description": "Cents (minor units of the currency)."
                    },
                    "balance": {},
                    "transactions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "direction": {},
                          "amount_cents": {
                            "type": "integer",
                            "description": "Cents (minor units of the currency)."
                          },
                          "reason": {},
                          "reference_type": {},
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/cross-cart": {
      "get": {
        "operationId": "get_cross_cart",
        "summary": "Your multi-brand cart",
        "description": "The key owner's own open cart across brands. Read-only.",
        "tags": [
          "Your key"
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "cart": {},
                        "items": {},
                        "by_brand": {},
                        "subtotal_cents": {
                          "type": "integer",
                          "description": "Cents (minor units of the currency)."
                        },
                        "item_count": {},
                        "brands": {},
                        "checkout": {}
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/deductions": {
      "get": {
        "operationId": "get_deductions",
        "summary": "Deductions taken off your settlements",
        "description": "Deductions on settlements where the key owner is the brand. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Only deductions with this status.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "applied",
                "disputed",
                "reversed"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "The whole stored row, every column the table has."
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/disputes": {
      "get": {
        "operationId": "get_disputes",
        "summary": "Your disputes",
        "description": "Disputes the key owner is on either side of. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Only disputes with this status.",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "investigating",
                "resolved",
                "rejected",
                "withdrawn"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "The whole stored row, every column the table has."
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/events": {
      "get": {
        "operationId": "get_events",
        "summary": "Your activity log",
        "description": "The key owner's own rows from the append-only events ledger. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "event_type",
            "in": "query",
            "required": false,
            "description": "Only events of this exact type.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "event_type": {},
                          "entity_type": {},
                          "entity_id": {
                            "type": "string"
                          },
                          "counterparty_id": {
                            "type": "string"
                          },
                          "payload": {},
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/flags": {
      "get": {
        "operationId": "get_flags",
        "summary": "Which features are switched on",
        "description": "The protocol's feature flags, read-only. Writing a flag is admin-only and not on this surface. Read-only.",
        "tags": [
          "Public"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {},
                    "version": {
                      "type": "string",
                      "const": "v1"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/fulfilments": {
      "post": {
        "operationId": "post_fulfilments",
        "summary": "Mark your leg of an order shipped",
        "description": "Marks the key owner's own leg of an order (a settlement where they are the shipping brand) as SHIPPED, with the carrier and tracking number, through the same door as the order screen: the tracking number is checked, the buyer is told and the custody trail is written. Shipped only — delivery stays with the carrier's proof and the buyer, because it releases money gates. No money moves. Needs a key with the write scope. Retries: on a 409, a 429 or a 5xx, send the same request again with the SAME Idempotency-Key; never retry another 4xx.",
        "tags": [
          "Your key"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "settlement_id",
                  "carrier"
                ],
                "properties": {
                  "settlement_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "From GET /api/v1/orders."
                  },
                  "carrier": {
                    "type": "string",
                    "description": "ups, fedex, usps, dhl … or other (then say who in shipping_provider or delivered_by)."
                  },
                  "tracking_number": {
                    "type": "string"
                  },
                  "shipping_provider": {
                    "type": "string"
                  },
                  "delivered_by": {
                    "type": "string",
                    "enum": [
                      "self",
                      "seller"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "settlement_id": {
                          "type": "string"
                        },
                        "fulfillment_status": {},
                        "tracking_number": {},
                        "carrier": {},
                        "track_url": {},
                        "custody": {}
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/gtin": {
      "get": {
        "operationId": "get_gtin",
        "summary": "Barcode lookup in your own catalog",
        "description": "The key owner's products matching a GTIN or UPC. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "gtin",
            "in": "query",
            "required": false,
            "description": "Exact GTIN.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "upc",
            "in": "query",
            "required": false,
            "description": "Exact item UPC.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {},
                          "sku": {},
                          "upc_item": {},
                          "gtin": {},
                          "gs1_prefix": {},
                          "brand_id": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/health": {
      "get": {
        "operationId": "get_health",
        "summary": "Is the API up",
        "description": "Answers when the API is serving. Reads nothing. Read-only.",
        "tags": [
          "Public"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {},
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "protocol": {},
                    "fee": {},
                    "permanent": {}
                  }
                }
              }
            }
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/item-setup": {
      "get": {
        "operationId": "get_item_setup",
        "summary": "Item-setup records for a retailer or distributor system",
        "description": "A brand's product records shaped for item setup, optionally laid out as a form. Reading another brand's items is recorded, and that brand can see the pull. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "brand_id",
            "in": "query",
            "required": false,
            "description": "The brand whose items to read. Defaults to the key owner.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "ids",
            "in": "query",
            "required": false,
            "description": "Comma-separated product uuids to limit the records to.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "template",
            "in": "query",
            "required": false,
            "description": "A form: builtin:pacoa, builtin:gs1, builtin:everything, or the id of one the key owner saved.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "brand": {},
                    "records": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {},
                          "sku": {},
                          "classes": {},
                          "units": {},
                          "values": {}
                        }
                      }
                    },
                    "form": {}
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/leaderboard": {
      "get": {
        "operationId": "get_leaderboard",
        "summary": "Standings by contribution score",
        "description": "Active participants ranked by contribution score. No contact details. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "role",
            "in": "query",
            "required": false,
            "description": "Only participants in this role.",
            "schema": {
              "type": "string",
              "enum": [
                "brand",
                "seller",
                "buyer",
                "distributor",
                "manufacturer",
                "merchandiser",
                "marketer",
                "shipper",
                "storer",
                "supplier",
                "funder"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {},
                          "handle": {},
                          "primary_role": {},
                          "contribution_score": {},
                          "contribution_tier": {},
                          "country": {}
                        }
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/map": {
      "get": {
        "operationId": "get_map",
        "summary": "Your advertised-price (MAP) policies",
        "description": "Minimum advertised price policies where the key owner is the brand. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "The whole stored row, every column the table has."
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/markdown": {
      "get": {
        "operationId": "get_markdown",
        "summary": "Your markdown rules",
        "description": "Automatic discounting rules where the key owner is the brand. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "The whole stored row, every column the table has."
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/mcp": {
      "get": {
        "operationId": "get_mcp",
        "summary": "The MCP server's description and tools",
        "description": "Server info, supported MCP protocol versions, how to sign in, and the tool list. Read-only.",
        "tags": [
          "Your key"
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "server": {},
                        "transport": {},
                        "protocolVersions": {},
                        "endpoint": {},
                        "auth": {},
                        "tools": {},
                        "readOnly": {}
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      },
      "post": {
        "operationId": "post_mcp",
        "summary": "MCP over Streamable HTTP (JSON responses)",
        "description": "One JSON-RPC 2.0 message per request: initialize, ping, tools/list, tools/call. Authenticated by your own API key, or by signing in with your GRAJ account from an MCP client (OAuth 2.1 with PKCE; discovery at /.well-known/oauth-protected-resource). Every tool answers about the signed-in account only; every tool but one reads, and that one (draft_order_for_customer) saves a draft the person places themselves. No batches; bodies over 64 KB are refused. Read-only.",
        "tags": [
          "Your key"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "jsonrpc",
                  "method"
                ],
                "properties": {
                  "jsonrpc": {
                    "const": "2.0"
                  },
                  "id": {
                    "type": [
                      "string",
                      "integer"
                    ]
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "initialize",
                      "ping",
                      "tools/list",
                      "tools/call"
                    ]
                  },
                  "params": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {},
                    "id": {},
                    "result": {},
                    "error": {}
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/notifications": {
      "get": {
        "operationId": "get_notifications",
        "summary": "Your notifications",
        "description": "The key owner's notifications. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "unread_only",
            "in": "query",
            "required": false,
            "description": "true for unread only.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "type": {},
                          "title": {},
                          "body": {},
                          "read": {},
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/operators": {
      "get": {
        "operationId": "get_operators",
        "summary": "Participant directory, any role",
        "description": "Public profiles of active participants (test and verification accounts excluded). Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Only participants in this country (exact match on the profile's country, up to 60 characters).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {},
                          "handle": {},
                          "primary_role": {},
                          "country": {},
                          "state": {},
                          "city": {},
                          "bio": {},
                          "logo_url": {},
                          "contribution_score": {},
                          "contribution_tier": {},
                          "status": {}
                        }
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/orders": {
      "get": {
        "operationId": "get_orders",
        "summary": "Your orders",
        "description": "Orders the key owner sold, bought or is paid on, newest first, with a total count. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Only orders with this status.",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "pending",
                "confirmed",
                "awaiting_fulfillment",
                "fulfilling",
                "shipped",
                "delivered",
                "closed",
                "cancelled",
                "refunded"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "order_number": {},
                          "seller_id": {
                            "type": "string"
                          },
                          "buyer_masked": {},
                          "party": {},
                          "status": {},
                          "payment_status": {},
                          "fulfillment_status": {},
                          "subtotal_cents": {
                            "type": "integer",
                            "description": "Cents (minor units of the currency)."
                          },
                          "discount_cents": {
                            "type": "integer",
                            "description": "Cents (minor units of the currency)."
                          },
                          "tax_cents": {
                            "type": "integer",
                            "description": "Cents (minor units of the currency)."
                          },
                          "protocol_fee_cents": {
                            "type": "integer",
                            "description": "Cents (minor units of the currency)."
                          },
                          "total_rep_commission_cents": {
                            "type": "integer",
                            "description": "Cents (minor units of the currency)."
                          },
                          "total_brand_payout_cents": {
                            "type": "integer",
                            "description": "Cents (minor units of the currency)."
                          },
                          "currency_code": {},
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "paid_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "delivered_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "count": {
                      "type": "integer"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "note": {}
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/price-changes": {
      "get": {
        "operationId": "get_price_changes",
        "summary": "Your repricing history",
        "description": "The key owner's own price-change events. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "event_type": {},
                          "entity_id": {
                            "type": "string"
                          },
                          "payload": {},
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/products": {
      "get": {
        "operationId": "get_products",
        "summary": "Active products",
        "description": "Active products, without the brand join. Prices are in cents. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "brand_id",
            "in": "query",
            "required": false,
            "description": "Only this brand's rows. Ignored if it is not a uuid.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Category contains this text (case-insensitive, up to 80 characters).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {},
                          "sku": {},
                          "brand_id": {
                            "type": "string"
                          },
                          "category": {},
                          "description": {},
                          "images": {},
                          "wholesale_price_cents": {
                            "type": "integer",
                            "description": "Cents (minor units of the currency)."
                          },
                          "suggested_retail_cents": {
                            "type": "integer",
                            "description": "Cents (minor units of the currency)."
                          },
                          "currency_code": {},
                          "minimum_order_qty": {},
                          "minimum_order_value_cents": {
                            "type": "integer",
                            "description": "Cents (minor units of the currency)."
                          },
                          "units_per_case": {},
                          "unit": {},
                          "lead_time_days": {},
                          "status": {},
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      },
      "post": {
        "operationId": "post_products",
        "summary": "Create one of your products",
        "description": "Creates a product in the key owner's own catalog, through the same door as the screen: the restricted-goods list, barcode check digits, the margin floor and the wholesale/DTC rule all apply, and followers are alerted when it goes live. Needs a key with the write scope. Send an Idempotency-Key header and a retry makes one product, not two (a repeat with the same key and body returns the first answer with Idempotent-Replayed: true; the same key with a different body is refused with 422). Prices are in cents. Retries: on a 409, a 429 or a 5xx, send the same request again with the SAME Idempotency-Key; never retry another 4xx.",
        "tags": [
          "Your key"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "sku": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "category": {
                    "type": "string"
                  },
                  "wholesale_price_cents": {
                    "type": "integer",
                    "description": "Cents (minor units)."
                  },
                  "suggested_retail_cents": {
                    "type": "integer",
                    "description": "Cents (minor units)."
                  },
                  "minimum_order_qty": {
                    "type": "integer"
                  },
                  "units_per_case": {
                    "type": "integer"
                  },
                  "gtin": {
                    "type": "string",
                    "description": "Refused if its GS1 check digit is wrong."
                  },
                  "wholesale_enabled": {
                    "type": "boolean"
                  },
                  "dtc_enabled": {
                    "type": "boolean"
                  },
                  "images": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "The whole stored row, every column the table has."
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      },
      "patch": {
        "operationId": "patch_products",
        "summary": "Change one of your products",
        "description": "Changes the key owner's own product — stock (inventory_units), prices, status and the other fields the screen edits — through the same door as the screen, margin floor included. Needs a key with the write scope; Idempotency-Key works as on POST. Retries: on a 409, a 429 or a 5xx, send the same request again with the SAME Idempotency-Key; never retry another 4xx.",
        "tags": [
          "Your key"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "inventory_units": {
                    "type": "integer"
                  },
                  "wholesale_price_cents": {
                    "type": "integer",
                    "description": "Cents (minor units)."
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "draft",
                      "active",
                      "inactive",
                      "discontinued"
                    ]
                  }
                },
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "The whole stored row, every column the table has."
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/promotions": {
      "get": {
        "operationId": "get_promotions",
        "summary": "Your promotions",
        "description": "Discounts the key owner runs. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Only promotions with this status.",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "paused",
                "ended"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "The whole stored row, every column the table has."
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/protocol": {
      "get": {
        "operationId": "get_protocol",
        "summary": "The protocol's headline numbers",
        "description": "Counts only (participants, orders, products, roadmap) and the 5% fee. No row of anybody's data. Read-only.",
        "tags": [
          "Public"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "protocol": {},
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "fee": {},
                    "permanent": {},
                    "operators": {},
                    "orders": {},
                    "products": {},
                    "roadmap": {},
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/receiving": {
      "get": {
        "operationId": "get_receiving",
        "summary": "Your receiving records",
        "description": "What the key owner confirmed arriving. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "order_id",
            "in": "query",
            "required": false,
            "description": "Only records for this order.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "The whole stored row, every column the table has."
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/reps": {
      "get": {
        "operationId": "get_reps",
        "summary": "Seller directory",
        "description": "Public profiles of active sellers, with the states they cover. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Only participants in this country (exact match on the profile's country, up to 60 characters).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {},
                          "handle": {},
                          "primary_role": {},
                          "country": {},
                          "state": {},
                          "city": {},
                          "bio": {},
                          "logo_url": {},
                          "contribution_score": {},
                          "contribution_tier": {},
                          "states_covered": {}
                        }
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/returns": {
      "get": {
        "operationId": "get_returns",
        "summary": "Your returns",
        "description": "Return disputes the key owner is on either side of. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "The whole stored row, every column the table has."
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/reviews": {
      "get": {
        "operationId": "get_reviews",
        "summary": "Published reviews",
        "description": "Published reviews of brands and products. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "brand_id",
            "in": "query",
            "required": false,
            "description": "Only this brand's rows. Ignored if it is not a uuid.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "product_id",
            "in": "query",
            "required": false,
            "description": "Only reviews of this product.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "brand_id": {
                            "type": "string"
                          },
                          "product_id": {
                            "type": "string"
                          },
                          "rating": {},
                          "title": {},
                          "comment": {},
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/roadmap": {
      "get": {
        "operationId": "get_roadmap",
        "summary": "The public roadmap",
        "description": "Every roadmap row (id, title, status, category, phase) and a count per status. Read-only.",
        "tags": [
          "Public"
        ],
        "security": [],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Only rows with this status.",
            "schema": {
              "type": "string",
              "enum": [
                "planned",
                "building",
                "shipped",
                "live",
                "in-prod",
                "done",
                "blocked",
                "superseded",
                "cancelled",
                "not-software",
                "withdrawn",
                "deferred"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "title": {},
                          "status": {},
                          "category": {},
                          "phase": {}
                        }
                      }
                    },
                    "returned": {},
                    "counts": {},
                    "total": {},
                    "in_production": {},
                    "pct_complete": {},
                    "version": {
                      "type": "string",
                      "const": "v1"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/samples": {
      "get": {
        "operationId": "get_samples",
        "summary": "Your sample requests",
        "description": "Sample requests where the key owner is the brand or the requester. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "The whole stored row, every column the table has."
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/score": {
      "get": {
        "operationId": "get_score",
        "summary": "Contribution score",
        "description": "With operator_id, that participant's score; without, the public top of the table. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "operator_id",
            "in": "query",
            "required": false,
            "description": "One participant. Prospects (unclaimed profiles) are never returned.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {},
                          "handle": {},
                          "primary_role": {},
                          "contribution_score": {},
                          "contribution_tier": {}
                        }
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/support": {
      "get": {
        "operationId": "get_support",
        "summary": "Your support tickets",
        "description": "The key owner's own support tickets. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Only tickets with this status.",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "pending",
                "resolved",
                "closed"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "topic": {},
                          "subject": {},
                          "description": {},
                          "priority": {},
                          "status": {},
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    },
    "/visits": {
      "get": {
        "operationId": "get_visits",
        "summary": "Your store visits",
        "description": "Visits the key owner made as a seller, or that were made to them as a buyer. Read-only.",
        "tags": [
          "Your key"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Rows to return, 1–200. Default 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Rows to skip. Default 0.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON, in the shape below.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "The whole stored row, every column the table has."
                      }
                    },
                    "version": {
                      "type": "string",
                      "const": "v1"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No API key, or an unknown, revoked or expired one."
          },
          "403": {
            "description": "The key lacks the scope, or the request came from an address the key does not allow."
          },
          "429": {
            "description": "Over 600 requests a minute on this key."
          },
          "500": {
            "description": "A fault on GRAJ's side. Nothing was changed."
          }
        }
      }
    }
  }
}
