# GraphQL basics Thor's Admin and Storefront APIs use separate GraphQL schemas. The same GraphQL concepts apply to both, but a field or input available in Admin is not automatically available in Storefront. Check the reference for the API your application is calling. ## Send a named operation and variables An operation declares which fields to return. Variables carry external input separately from the document, which avoids interpolating user data into GraphQL syntax. Admin API ```graphql query FindProducts($first: Int!, $query: String) { products(first: $first, query: $query) { nodes { id name slug } pageInfo { hasNextPage endCursor } } } ``` Variables ```json { "first": 10, "query": "tag:lighting" } ``` Send the document as the JSON request's `query` and the Variables tab as `variables`. Use the project endpoint and credential from [Connect to a project](/getting-started/connect). Name operations so failures can be traced to a useful purpose such as `FindProducts`. ## Read types accurately | Type | Meaning | | --- | --- | | `Product` | May be null | | `Product!` | Must be present in a successful value | | `[Product]` | The list and its entries may be null | | `[Product!]!` | The list and its entries are non-null | A missing optional value can be a normal business state. Do not force generated types to pretend a price or image always exists. A required input field must be supplied even when the surrounding input object is itself optional. JSON variables represent enums as strings. Inline GraphQL enum values are unquoted. Omitted input fields and explicit nulls can have different update behavior; follow the input field description rather than converting every missing value to null. ## Reuse selections with fragments Fragments keep shared selections consistent. For interfaces and unions, select `__typename` and use inline fragments for the concrete fields your client needs. This is especially useful for payment sessions, metafields, and mutation errors. Regenerate client types after changing operation documents. Do not edit generated output by hand. ## Handle the complete result Inspect HTTP status, top-level GraphQL errors, and mutation payload errors. A mutation can return HTTP 200 while rejecting the business action. See [Errors and retries](/concepts/operations/errors-and-retries) for one shared error-handling contract. Use [Pagination](/concepts/pagination) for connections, [Search query language](/concepts/query-language) for query expressions, and the API reference for exact fields.