Global.Church Developer Portal
For App Developers

SPARQL Quickstart

This guide walks through five SPARQL queries you can run against the Global.Church knowledge graph. Each example shows both a curl command and a JavaScript fetch equivalent.

All queries go through the API gateway at https://api.global.church/v0/sparql. You need an API key -- get one from the developer portal at platform.global.church/developer.

Authentication

Every request requires an Authorization header with your API key:

Code
Authorization: Bearer YOUR_API_KEY

The SPARQL endpoint accepts POST requests with Content-Type: application/sparql-query. Responses come back as application/sparql-results+json by default.


Query 1: Count All Triples

A simple health check -- how much data is in the graph?

Code
SELECT (COUNT(*) AS ?count) WHERE { ?s ?p ?o }

curl:

TerminalCode
curl -X POST \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/sparql-query" \ -d 'SELECT (COUNT(*) AS ?count) WHERE { ?s ?p ?o }' \ "https://api.global.church/v0/sparql"

JavaScript:

JavascriptCode
const query = `SELECT (COUNT(*) AS ?count) WHERE { ?s ?p ?o }`; const response = await fetch("https://api.global.church/v0/sparql", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/sparql-query", }, body: query, }); const data = await response.json(); console.log("Triple count:", data.results.bindings[0].count.value);

What to expect: A single row with a count value. The current graph has approximately 3.2 million triples across all named graphs.


Query 2: List Organizations in a Country

Find organizations by country code, with optional city and state.

Code
PREFIX gc: <https://ontology.global.church/core#> SELECT ?name ?city ?state WHERE { ?org a gc:Organization ; gc:orgName ?name ; gc:country "US" . OPTIONAL { ?org gc:city ?city } OPTIONAL { ?org gc:state ?state } } LIMIT 20

curl:

TerminalCode
curl -X POST \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/sparql-query" \ -d 'PREFIX gc: <https://ontology.global.church/core#> SELECT ?name ?city ?state WHERE { ?org a gc:Organization ; gc:orgName ?name ; gc:country "US" . OPTIONAL { ?org gc:city ?city } OPTIONAL { ?org gc:state ?state } } LIMIT 20' \ "https://api.global.church/v0/sparql"

JavaScript:

JavascriptCode
const query = ` PREFIX gc: <https://ontology.global.church/core#> SELECT ?name ?city ?state WHERE { ?org a gc:Organization ; gc:orgName ?name ; gc:country "US" . OPTIONAL { ?org gc:city ?city } OPTIONAL { ?org gc:state ?state } } LIMIT 20`; const response = await fetch("https://api.global.church/v0/sparql", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/sparql-query", }, body: query, }); const data = await response.json(); data.results.bindings.forEach((row) => { console.log(row.name.value, row.city?.value, row.state?.value); });

What to expect: Up to 20 rows, each with an organization name and optionally a city and state. The graph contains 37,000+ organizations materialized from Supabase. Change "US" to any ISO 3166-1 alpha-2 country code.


Query 3: Find Unengaged People Groups

People groups with no known engagement activity from any organization.

Code
PREFIX gc: <https://ontology.global.church/core#> PREFIX jp: <https://ontology.global.church/joshuaproject#> SELECT ?pgName ?country WHERE { ?pg a gc:PeopleGroup ; gc:peopleName ?pgName ; gc:country ?country . FILTER NOT EXISTS { ?activity gc:engagesPeopleGroup ?pg } } LIMIT 20

curl:

TerminalCode
curl -X POST \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/sparql-query" \ -d 'PREFIX gc: <https://ontology.global.church/core#> PREFIX jp: <https://ontology.global.church/joshuaproject#> SELECT ?pgName ?country WHERE { ?pg a gc:PeopleGroup ; gc:peopleName ?pgName ; gc:country ?country . FILTER NOT EXISTS { ?activity gc:engagesPeopleGroup ?pg } } LIMIT 20' \ "https://api.global.church/v0/sparql"

JavaScript:

JavascriptCode
const query = ` PREFIX gc: <https://ontology.global.church/core#> PREFIX jp: <https://ontology.global.church/joshuaproject#> SELECT ?pgName ?country WHERE { ?pg a gc:PeopleGroup ; gc:peopleName ?pgName ; gc:country ?country . FILTER NOT EXISTS { ?activity gc:engagesPeopleGroup ?pg } } LIMIT 20`; const response = await fetch("https://api.global.church/v0/sparql", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/sparql-query", }, body: query, }); const data = await response.json(); data.results.bindings.forEach((row) => { console.log(row.pgName.value, "in", row.country.value); });

What to expect: People group names and country codes where no engagement has been recorded. Note the open-world caveat: "no known engagement" means no engagement triple exists in the graph -- it could mean unengaged or simply unreported. The FILTER NOT EXISTS pattern is the standard way to find gaps in RDF data.


Query 4: Get Assessment Data for a People Group

Uses the 3-block pattern: PeopleGroup + Assessment + AssessmentResult. Assessment data (JP Scale, percent Christian, etc.) lives on gc:AssessmentResult, not directly on the people group.

Code
PREFIX gc: <https://ontology.global.church/core#> PREFIX jp: <https://ontology.global.church/joshuaproject#> SELECT ?pgName ?jpScale ?percentChristian WHERE { ?pg a gc:PeopleGroup ; gc:peopleName ?pgName . ?result a gc:AssessmentResult ; gc:resultForPeopleGroup ?pg ; jp:jpScale ?jpScale ; jp:percentChristian ?percentChristian . } LIMIT 20

curl:

TerminalCode
curl -X POST \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/sparql-query" \ -d 'PREFIX gc: <https://ontology.global.church/core#> PREFIX jp: <https://ontology.global.church/joshuaproject#> SELECT ?pgName ?jpScale ?percentChristian WHERE { ?pg a gc:PeopleGroup ; gc:peopleName ?pgName . ?result a gc:AssessmentResult ; gc:resultForPeopleGroup ?pg ; jp:jpScale ?jpScale ; jp:percentChristian ?percentChristian . } LIMIT 20' \ "https://api.global.church/v0/sparql"

JavaScript:

JavascriptCode
const query = ` PREFIX gc: <https://ontology.global.church/core#> PREFIX jp: <https://ontology.global.church/joshuaproject#> SELECT ?pgName ?jpScale ?percentChristian WHERE { ?pg a gc:PeopleGroup ; gc:peopleName ?pgName . ?result a gc:AssessmentResult ; gc:resultForPeopleGroup ?pg ; jp:jpScale ?jpScale ; jp:percentChristian ?percentChristian . } LIMIT 20`; const response = await fetch("https://api.global.church/v0/sparql", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/sparql-query", }, body: query, }); const data = await response.json(); data.results.bindings.forEach((row) => { console.log( row.pgName.value, "JP Scale:", row.jpScale.value, "% Christian:", row.percentChristian.value ); });

What to expect: People group names with their Joshua Project progress scale value (1-5) and percentage of Christian adherents. This is the 3-block assessment pattern used throughout the knowledge graph -- assessment metrics are always on gc:AssessmentResult, linked to the people group via gc:resultForPeopleGroup. Both Joshua Project and IMB data follow this same pattern.


Query 5: Search Organizations with Coordinates

Find organizations that have latitude and longitude data.

Code
PREFIX gc: <https://ontology.global.church/core#> SELECT ?name ?lat ?lng WHERE { ?org a gc:Organization ; gc:orgName ?name ; gc:latitude ?lat ; gc:longitude ?lng . } LIMIT 10

curl:

TerminalCode
curl -X POST \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/sparql-query" \ -d 'PREFIX gc: <https://ontology.global.church/core#> SELECT ?name ?lat ?lng WHERE { ?org a gc:Organization ; gc:orgName ?name ; gc:latitude ?lat ; gc:longitude ?lng . } LIMIT 10' \ "https://api.global.church/v0/sparql"

JavaScript:

JavascriptCode
const query = ` PREFIX gc: <https://ontology.global.church/core#> SELECT ?name ?lat ?lng WHERE { ?org a gc:Organization ; gc:orgName ?name ; gc:latitude ?lat ; gc:longitude ?lng . } LIMIT 10`; const response = await fetch("https://api.global.church/v0/sparql", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/sparql-query", }, body: query, }); const data = await response.json(); data.results.bindings.forEach((row) => { console.log(row.name.value, `(${row.lat.value}, ${row.lng.value})`); });

What to expect: Organization names with their geographic coordinates. Not all organizations have coordinates -- many have only city/state/country. You can combine this with a FILTER to search within a bounding box for geographic proximity queries.


Query 6: Compare Assessment Sources for a People Group

Different organizations assess the same people group using different methodologies. This query retrieves JP and IMB assessments side by side, showing which methodology each used.

Code
PREFIX gc: <https://ontology.global.church/core#> PREFIX jp: <https://ontology.global.church/joshuaproject#> PREFIX imb: <https://ontology.global.church/imb#> PREFIX skos: <http://www.w3.org/2004/02/skos/core#> SELECT ?pgName ?source ?methodology ?jpScale ?gsec WHERE { ?pg a gc:PeopleGroup ; gc:peopleName ?pgName . FILTER(?pgName = "Shaikh") ?result a gc:AssessmentResult ; gc:resultForPeopleGroup ?pg . ?assessment a gc:Assessment ; prov:generated ?result ; prov:wasAssociatedWith ?org ; gc:assessmentMethodology ?method . ?org gc:orgName ?source . ?method skos:prefLabel ?methodology . OPTIONAL { ?result jp:jpScale ?jpScale } OPTIONAL { ?result imb:gsecLevel/skos:prefLabel ?gsec } } LIMIT 10

curl:

TerminalCode
curl -X POST \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/sparql-query" \ -d 'PREFIX gc: <https://ontology.global.church/core#> PREFIX jp: <https://ontology.global.church/joshuaproject#> PREFIX imb: <https://ontology.global.church/imb#> PREFIX skos: <http://www.w3.org/2004/02/skos/core#> SELECT ?pgName ?source ?methodology ?jpScale ?gsec WHERE { ?pg a gc:PeopleGroup ; gc:peopleName ?pgName . FILTER(?pgName = "Shaikh") ?result a gc:AssessmentResult ; gc:resultForPeopleGroup ?pg . ?assessment a gc:Assessment ; prov:generated ?result ; prov:wasAssociatedWith ?org ; gc:assessmentMethodology ?method . ?org gc:orgName ?source . ?method skos:prefLabel ?methodology . OPTIONAL { ?result jp:jpScale ?jpScale } OPTIONAL { ?result imb:gsecLevel/skos:prefLabel ?gsec } } LIMIT 10' \ "https://api.global.church/v0/sparql"

What to expect: Rows showing the same people group assessed by different organizations (Joshua Project, IMB), each with their assessment methodology name. JP results will have jpScale populated; IMB results will have gsec populated. This demonstrates how the 3-block assessment pattern preserves multiple perspectives with full provenance.


Response Format

All queries return SPARQL Results JSON. The structure looks like this:

JSONCode
{ "head": { "vars": ["name", "city", "state"] }, "results": { "bindings": [ { "name": { "type": "literal", "value": "Example Church" }, "city": { "type": "literal", "value": "Denver" } } ] } }

Each binding is an object where keys match the SELECT variable names. Optional values (from OPTIONAL clauses) may be missing from individual bindings.

Rate Limits

The API gateway enforces 100 requests per minute per API key. For bulk data needs, consider requesting a higher limit or using the ingest API to contribute data directly.

Next Steps

Last modified on