Hello! Is there any reason I would get different results between these two methods of querying data? ```curl <https://xuaf19yr.api.sanity.io/v1/data/query/production>\?query\=\*%5B_type%20%...

8 replies
Last updated: Jan 12, 2021
Hello! Is there any reason I would get different results between these two methods of querying data?

curl <https://xuaf19yr.api.sanity.io/v1/data/query/production>\?query\=\*%5B_type%20%3D%3D%20%22articlePage%22%5D%20%7B%0A%09...%0A%7D

const sanity = require('@sanity/client')

const sanityClient = sanity({
  projectId: 'xuaf19yr',
  dataset: 'production',
  useCdn: false,
})

await sanityClient.fetch(`
  *[_type == "articlePage"] {
    ...
  }
`)
Any help appreciated!
AI Update

Yes! The most likely reason you're getting different results is due to API versioning and perspective differences between your two query methods.

The Key Differences

1. API Version Default

Your curl request is hitting the API directly without specifying an apiVersion, which means it defaults to v1 of the API. However, your @sanity/client code also doesn't specify an apiVersion, which similarly defaults to v1 - but there's a catch with how the client behaves.

2. Perspective Default (Most Likely Culprit)

The bigger issue is likely the perspective. As of API version 2025-02-19, the default perspective changed from raw to published. However, when you use an authenticated token with @sanity/client, the behavior can differ:

  • Direct HTTP API calls (your curl): Returns only published documents by default
  • @sanity/client with token: May return different results depending on token permissions and configuration

The Solution

Make your @sanity/client configuration explicit to ensure consistent behavior:

const sanity = require('@sanity/client')

const sanityClient = sanity({
  projectId: 'xuaf19yr',
  dataset: 'production',
  useCdn: false,
  apiVersion: '2025-02-19', // Always specify this!
  perspective: 'published',  // Explicitly set perspective
})

await sanityClient.fetch(`
  *[_type == "articlePage"] {
    ...
  }
`)

Why This Matters

Without specifying apiVersion and perspective:

  • You might be seeing draft documents mixed with published ones (if using the raw perspective)
  • GROQ operator behavior can differ between v1 and newer versions
  • The client might use different defaults than the direct HTTP API

The perspective setting controls which document versions you see:

  • published - Only published documents (recommended for production)
  • previewDrafts - Drafts if they exist, otherwise published
  • raw - Everything including both drafts and published

Always explicitly set both apiVersion and perspective in your client configuration to avoid surprises!

Actually, I do get the same result!
However, locally using "Vision" in Studio I'm getting the result I am expecting. I am probably missing something here.
What's the result you are not getting that you'd like to get?
If it's something like including
drafts.<id>
documents in your results, this will require a read token as these documents are on a so-called non-root path (they have a
.
in the ID) and therefore private even in a public dataset.
To set up a read token, go to your project on
manage.sanity.io , then to Settings and API. You should see an option there to add a new token. If you create a read token, you can then add it to the client configuration as follows:
const sanityClient = sanity({
  projectId: 'xuaf19yr',
  dataset: 'production',
  token: '<SANITY_READ_TOKEN>'
  useCdn: false,
})
Thank you for your reply
user M
! Using a token I'm getting the results I'm expecting!
Very helpful and a huge load off my shoulders!
Glad to hear! Was there anywhere you checked in the documentation and expecting to find this information? Just in case we can make it more visible 🙂
I’m not sure to be honest, I encountered this while using the seemingly excellent https://github.com/LiamMartens/sanity-plugin-intl-input . The plugin namespaces translated documents using i18n.&lt;id&gt;, which explains the issue. Maybe it would be a good idea for the plugin author to mention this somewhere in the plugin documentation, I’ll mention it when closing the issue I opened regarding this.
Thanks Jacob, that's great feedback indeed. I think Liam (the plugin's author) is considering adding the option to either use non-root paths or the former notation that put the i18n info at the back of the ID without a
.
. Feels like a good opportunity to add the note you suggested alongside the option itself 🙂

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?