We build custom applications 5x faster and cheaper 🚀
Book a Free Consultation
Stuck on an error? Book a 30-minute call with an engineer and get a direct fix + next steps. No pressure, no commitment.
A direct, practical answer: set up a Google Cloud project and create credentials (choose OAuth2 for user-granted access or a service account for server-to-server), enable the Google Sheets API (and Drive API if you will use push notifications), then install/configure an OpenClaw skill through ClawHub that holds your credentials as secure environment variables or secrets. Implement the skill so it explicitly requests and stores short-lived access tokens (or uses a service-account JWT exchange) and calls the Sheets REST API (sheets.googleapis.com) to read/write ranges. Keep webhooks and any persistent state (queues, refresh-token storage, long-lived scheduling) outside the OpenClaw agent runtime (in your web server or cloud service), validate webhooks, respect scopes and consent, and debug by inspecting HTTP responses, token scopes/expiry, and logs.
https://accounts.google.com/o/oauth2/v2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fspreadsheets%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive&access_type=offline&include_granted_scopes=true&response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI
curl -s -X POST https://oauth2.googleapis.com/token \\ -H "Content-Type: application/x-www-form-urlencoded" \\ -d "code=AUTH_CODE&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&redirect_uri=YOUR_REDIRECT_URI&grant_type=authorization_code"
curl -s -X POST https://oauth2.googleapis.com/token \\ -H "Content-Type: application/x-www-form-urlencoded" \\ -d "client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=refresh_token&refresh_token=REFRESH_TOKEN"
// Load service account JSON (downloaded from Google Cloud console)
const sa = JSON.parse(fs.readFileSync('./service-account.json', 'utf8'));
const iat = Math.floor(Date.now() / 1000);
const exp = iat + 3600;
const scopes = 'https://www.googleapis.com/auth/spreadsheets';
const claim = {
iss: sa.client_email,
scope: scopes,
aud: 'https://oauth2.googleapis.com/token',
exp,
iat
};
// Sign JWT with the service account private key
const signedJwt = jwt.sign(claim, sa.private_key, { algorithm: 'RS256' });
// Exchange JWT for access token
async function getAccessToken() {
const resp = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=${encodeURIComponent(signedJwt)}
});
const body = await resp.json();
if (!resp.ok) throw new Error(JSON.stringify(body));
return body.access_token;
}
// Call Sheets API
async function readRange(spreadsheetId, range) {
const token = await getAccessToken();
const r = await fetch(https://sheets.googleapis.com/v4/spreadsheets/${spreadsheetId}/values/${encodeURIComponent(range)}, {
headers: { Authorization: Bearer ${token} }
});
return r.json();
}
// // Example usage
readRange('your-spreadsheet-id', 'Sheet1!A1:C10').then(console.log).catch(console.error);
```
curl -H "Authorization: Bearer ACCESS\_TOKEN" \\ "https://sheets.googleapis.com/v4/spreadsheets/SPREADSHEET\_ID/values/Sheet1!A1:D10"
curl -X PUT -H "Authorization: Bearer ACCESS\_TOKEN" -H "Content-Type: application/json" \\
-d '{"range": "Sheet1!A1:B2","majorDimension":"ROWS","values":[["a","b"],["c","d"]]}' \\
"https://sheets.googleapis.com/v4/spreadsheets/SPREADSHEET\_ID/values/Sheet1!A1:B2?valueInputOption=RAW"
Speak one‑on‑one with a senior engineer about your no‑code app, migration goals, and budget. In just half an hour you’ll leave with clear, actionable next steps—no strings attached.
1
A 403 means the service account identity you're using does not have permission to open that spreadsheet. Grant the account access (or impersonate a user with access) and confirm the correct credentials, scopes, and APIs are configured.
// Node.js example using googleapis
const {google} = require('googleapis');
const keys = JSON.parse(process.env.SERVICE_ACCOUNT_KEY_JSON);
const auth = new google.auth.GoogleAuth({
credentials: keys,
scopes: ['https://www.googleapis.com/auth/spreadsheets'],
});
const sheets = google.sheets({version:'v4', auth});
await sheets.spreadsheets.get({spreadsheetId: 'SPREADSHEET_ID'});
2
Direct answer: Ensure the Claw Job schema the skill expects matches your database — either migrate the table to add/rename columns, or create a compatibility view/adapter and update the skill’s SQL/mapping; then validate in the OpenClaw runtime and check skill logs for schema errors.
Do this:
// create compatibility view mapping renamed columns
CREATE VIEW jobs_compat AS
SELECT id, new_name AS job_name, created_at FROM jobs;
// update skill query to use compatibility view
// using node-postgres
const res = await client.query('SELECT id, job_name, created_at FROM jobs_compat');
3
Handle HTTP 429 by treating it as a real signal: read Retry-After (or use exponential backoff with jitter), throttle requests, honor per-skill and per-agent quotas, and move durable retry/queue state outside the OpenClaw runtime for production. Configure retry parameters via environment variables, log each 429 with context, and expose metrics so throttling is observable.
// Node fetch with backoff
async function call(api){let backoff=500;for(let i=0;i<6;i++){let r=await fetch(api);// <b>//</b> handle 429
if(r.status!==429) return r;let ra=r.headers.get('Retry-After');await new Promise(s=>setTimeout(s, ra?ra*1000:backoff));backoff*=2+Math.random();}
throw new Error('rate limited');
}
4
Direct answer: When you get OAuth errors like invalid_grant or expired_token on refresh, treat them as signals that the refresh token is invalid, revoked, expired, or mismatched — the only reliable fix is reauthorization (full OAuth flow) after diagnosing root cause.
Check server response, timestamps, and logs; verify client_id/secret, token endpoint, scopes, and whether refresh tokens are single-use or rotated. Ensure clock sync and that tokens are stored outside the agent runtime (env vars or secure store). If rotated or revoked, trigger a fresh auth flow, persist new tokens, and add retry with exponential backoff and clear audit logs.
This prompt helps an AI assistant understand your setup and guide you through the fix step by step, without assuming technical knowledge.
From startups to enterprises and everything in between, see for yourself our incredible impact.
Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We’ll discuss your project and provide a custom quote at no cost.Â