π REST API for retrieving data from Google Sheets in JSON format with filtering and pagination support.
This project provides a simple and powerful REST API for reading data from Google Sheets. Perfect for:
- Creating public APIs based on Google Sheets
- Integrating Google Sheets with web applications
- Rapid API prototyping without a database
- CMS based on Google Sheets
- β Real-time data reading from Google Sheets
- β Filtering by any columns via query parameters
- β Pagination for handling large spreadsheets
- β Rate Limiting - DDoS protection (60 requests/minute per IP)
- β Automatic documentation - Swagger UI and ReDoc
- β Async processing - high performance
- β CORS - browser request support
- β Docker - containerization ready
- β Type hints - fully typed code
Note: This is a read-only API. It retrieves data from Google Sheets but does not support write operations (POST/PUT/DELETE). The service account only requires Viewer permissions.
- Python 3.10+
- FastAPI - modern web framework
- gspread - Google Sheets API client
- google-auth - service account authentication
- uvicorn - ASGI server
- slowapi - rate limiting
git clone https://github.com/VernaculusF/gsheets-json-api.git
cd gsheets-json-api# Windows
python -m venv venv
venv\Scripts\activate
# Linux/Mac
python3 -m venv venv
source venv/bin/activatepip install -r requirements.txt- Go to Google Cloud Console
- Create a new project or select an existing one
- Enable Google Sheets API:
- In the menu, select "APIs & Services" β "Enable APIs and Services"
- Search for "Google Sheets API" and enable it
- Go to "APIs & Services" β "Credentials"
- Click "Create Credentials" β "Service Account"
- Fill in:
- Service account name:
gsheets-api-service - Service account ID: auto-generated
- Click "Create and Continue"
- Service account name:
- Role: can be skipped (not required for Sheets API)
- Click "Done"
- In the service accounts list, click on the created account
- Go to the "Keys" tab
- Click "Add Key" β "Create new key"
- Select JSON format
- Download the file - this is your
creds.json
# Move the downloaded file to the project root
mv ~/Downloads/your-project-xxxxx.json creds.jsoncreds.json to git! The file is already added to .gitignore.
- Open your Google Sheets spreadsheet
- Click the "Share" button
- Copy the email of the service account from
creds.json:"client_email": "gsheets-api-service@your-project.iam.gserviceaccount.com"
- Paste this email into the "Add people and groups" field
- Set permissions to Viewer (read-only)
- Click "Send"
# Copy the example
cp .env.example .env
# Edit the .env fileFill in .env:
# Spreadsheet ID (from Google Sheets URL)
# https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
# ^^^^^^^^ this is SPREADSHEET_ID ^^^^^^^^
SPREADSHEET_ID=1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms
# Sheet name in the spreadsheet (default "Sheet1")
SHEET_NAME=Sheet1
# Server port
PORT=8000
# Logging level (DEBUG, INFO, WARNING, ERROR)
LOG_LEVEL=INFOThe spreadsheet must have headers in the first row:
| Name | Age | City | |
|---|---|---|---|
| Alice | 30 | Moscow | alice@example.com |
| Bob | 25 | SPb | bob@example.com |
| Charlie | 35 | Kazan | charlie@example.com |
- First row = headers (JSON keys)
- Other rows = data (JSON values)
# Activate virtual environment
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
# Start the server
python app.py
# Or via uvicorn directly
uvicorn app:app --reload --port 8000The server will be available at http://localhost:8000
After starting, open in your browser:
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
# Get all data (first 100 records)
curl http://localhost:8000/api/dataResponse:
{
"total": 3,
"limit": 100,
"offset": 0,
"filters_applied": null,
"data": [
{
"Name": "Alice",
"Age": "30",
"City": "Moscow",
"Email": "alice@example.com"
},
{
"Name": "Bob",
"Age": "25",
"City": "SPb",
"Email": "bob@example.com"
},
{
"Name": "Charlie",
"Age": "35",
"City": "Kazan",
"Email": "charlie@example.com"
}
]
}# Filter by city
curl "http://localhost:8000/api/data?city=Moscow"
# Filter by age
curl "http://localhost:8000/api/data?age=30"
# Search by name (partial match)
curl "http://localhost:8000/api/data?name=Ali"
# Combined filters
curl "http://localhost:8000/api/data?city=Moscow&age=30"# First 10 records
curl "http://localhost:8000/api/data?limit=10&offset=0"
# Next 10 records
curl "http://localhost:8000/api/data?limit=10&offset=10"
# With filter and pagination
curl "http://localhost:8000/api/data?city=Moscow&limit=5&offset=0"curl http://localhost:8000/healthResponse:
{
"status": "ok",
"service": "gsheets-json-api",
"version": "1.0.0",
"environment": "development"
}docker build -t gsheets-json-api .docker run -d \
-p 8000:8000 \
-e SPREADSHEET_ID=your_spreadsheet_id \
-e SHEET_NAME=Sheet1 \
-v $(pwd)/creds.json:/app/creds.json:ro \
--name gsheets-api \
gsheets-json-api# Start all services
docker-compose up -d
# View logs
docker-compose logs -f api
# Stop
docker-compose down- Install Google Cloud SDK
- Authenticate:
gcloud auth login
# Create secret with creds.json contents
gcloud secrets create gsheets-creds \
--data-file=creds.json \
--replication-policy=automatic# Build and upload image
gcloud builds submit --tag gcr.io/YOUR_PROJECT_ID/gsheets-api
# Deploy to Cloud Run
gcloud run deploy gsheets-api \
--image gcr.io/YOUR_PROJECT_ID/gsheets-api \
--platform managed \
--region us-central1 \
--allow-unauthenticated \
--set-env-vars SPREADSHEET_ID=your_spreadsheet_id,SHEET_NAME=Sheet1 \
--set-secrets /app/creds.json=gsheets-creds:latestAfter deployment, you'll get a URL like:
https://gsheets-api-xxxxx-uc.a.run.app
# Repeat build and deploy commands
gcloud builds submit --tag gcr.io/YOUR_PROJECT_ID/gsheets-api
gcloud run deploy gsheets-api --image gcr.io/YOUR_PROJECT_ID/gsheets-apipip install -r requirements-dev.txt# All tests
pytest
# With code coverage
pytest --cov=. --cov-report=html
# Specific file
pytest tests/test_api.py -v# Code formatting
black .
isort .
# Style check
flake8 .
# Type checking
mypy app.py sheets_client.py config.pyCause: Invalid or missing creds.json
Solution:
- Check that the
creds.jsonfile exists - Verify JSON format (must be valid)
- Ensure Google Sheets API is enabled in the project
Cause: Spreadsheet is not shared with the service account
Solution:
- Open the Google Sheets spreadsheet
- Click "Share"
- Add the email from
client_emailincreds.json - Set Viewer permissions
Cause: Incorrect sheet name in .env
Solution:
- Check the exact sheet name in Google Sheets (case-sensitive)
- Update
SHEET_NAMEin the.envfile
Cause: Rate limit exceeded (60/minute)
Solution:
- Wait 1 minute
- Reduce request frequency
- Configure a different limit in
app.py(@limiter.limit("60/minute"))
Causes:
- The spreadsheet is actually empty
- The first row doesn't contain headers
- All data is filtered out
Solution:
- Check the spreadsheet contents
- Ensure the first row contains headers
- Check the filters in the request
- FastAPI documentation
- gspread documentation
- Google Cloud Console
- Google Sheets API
- Cloud Run documentation
Pull requests are welcome! For major changes, please open an issue first to discuss.
Your Name - @yourhandle
If you found this project helpful, give it a star β on GitHub!
Made with β€οΈ and FastAPI