UrlFetchApp basis
UrlFetchApp geeft Apps Script de mogelijkheid om HTTP-verzoeken te doen naar externe diensten. Je kunt REST-APIs aanroepen, webhooks triggeren, bestanden downloaden en data naar externe systemen sturen.
function basisGet() {
const response = UrlFetchApp.fetch('https://httpbin.org/get');
const statusCode = response.getResponseCode();
const body = response.getContentText();
Logger.log(`Status: ${statusCode}`);
Logger.log(body.substring(0, 200));
}
GET met query-parameters
function getMetParameters() {
const basisUrl = 'https://api.voorbeeld.nl/producten';
const params = {
categorie: 'elektronica',
pagina: 1,
perPagina: 50,
sortering: 'prijs_asc',
};
const queryString = Object.entries(params)
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
.join('&');
const url = `${basisUrl}?${queryString}`;
const response = UrlFetchApp.fetch(url, {muteHttpExceptions: true});
if (response.getResponseCode() !== 200) {
Logger.log(`Fout: ${response.getResponseCode()}: ${response.getContentText()}`);
return null;
}
return JSON.parse(response.getContentText());
}
POST met JSON body
function postJsonData() {
const url = 'https://api.voorbeeld.nl/orders';
const data = {
klantId: 'KL-001',
producten: [{id: 'P-123', aantal: 2}, {id: 'P-456', aantal: 1}],
bezorgAdres: 'Damrak 1, Amsterdam',
};
const opties = {
method: 'POST',
contentType: 'application/json',
payload: JSON.stringify(data),
headers: {
'Authorization': 'Bearer ' + PropertiesService.getScriptProperties().getProperty('API_TOKEN'),
'X-Request-ID': Utilities.getUuid(),
},
muteHttpExceptions: true,
};
const response = UrlFetchApp.fetch(url, opties);
const statusCode = response.getResponseCode();
if (statusCode >= 200 && statusCode < 300) {
Logger.log('Order aangemaakt: ' + response.getContentText());
return JSON.parse(response.getContentText());
} else {
throw new Error(`API-fout ${statusCode}: ${response.getContentText()}`);
}
}
Zet muteHttpExceptions aan bij eigen foutafhandeling
Gebruik altijd muteHttpExceptions: true als je HTTP-fouten zelf wilt afhandelen. Zonder deze optie gooit Apps Script een fout bij elke 4xx- of 5xx-respons, waarna je de response-body niet meer kunt lezen.
Authenticatie-patronen
Bewaar tokens en wachtwoorden nooit hardcoded in je script. Zet ze in PropertiesService.getScriptProperties() of in Script properties via het projectinstellingenscherm, zodat ze niet in de broncode of in versiebeheer terechtkomen.
function basicAuth() {
const gebruiker = 'api_gebruiker';
const wachtwoord = PropertiesService.getScriptProperties().getProperty('API_PASS');
const encoded = Utilities.base64Encode(`${gebruiker}:${wachtwoord}`);
const response = UrlFetchApp.fetch('https://api.voorbeeld.nl/data', {
headers: {
'Authorization': `Basic ${encoded}`,
},
});
return JSON.parse(response.getContentText());
}
function bearerToken() {
const token = PropertiesService.getScriptProperties().getProperty('BEARER_TOKEN');
const response = UrlFetchApp.fetch('https://api.voorbeeld.nl/me', {
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
},
});
return JSON.parse(response.getContentText());
}
Gebruik OAuth waar het kan
Voor Google-eigen APIs en veel populaire diensten kun je in plaats van handmatige tokens de OAuth2-bibliotheek of ScriptApp.getOAuthToken() gebruiken. Dat voorkomt dat je zelf langlevende geheimen moet beheren en verlengen.
Parallelle aanroepen met fetchAll
Met fetchAll voer je meerdere verzoeken tegelijk uit in plaats van één voor één. Dat scheelt veel doorlooptijd als je tientallen onafhankelijke aanroepen moet doen.
function parallelleAanroepen() {
const urls = [
'https://api.voorbeeld.nl/gebruiker/1',
'https://api.voorbeeld.nl/gebruiker/2',
'https://api.voorbeeld.nl/gebruiker/3',
];
const verzoeken = urls.map(url => ({
url,
method: 'GET',
headers: {
'Authorization': 'Bearer ' + PropertiesService.getScriptProperties().getProperty('API_TOKEN'),
},
muteHttpExceptions: true,
}));
const responses = UrlFetchApp.fetchAll(verzoeken);
responses.forEach((response, idx) => {
if (response.getResponseCode() === 200) {
const data = JSON.parse(response.getContentText());
Logger.log(`Gebruiker ${idx + 1}: ${data.naam}`);
}
});
}
Bestanden downloaden en uploaden
function downloadBestand(url, bestandsnaam) {
const response = UrlFetchApp.fetch(url);
const blob = response.getBlob();
blob.setName(bestandsnaam);
const map = DriveApp.getFolderById('MAP_ID');
const bestand = map.createFile(blob);
Logger.log(`Opgeslagen: ${bestand.getUrl()}`);
return bestand;
}
function uploadBestandNaarApi(driveBestandId) {
const bestand = DriveApp.getFileById(driveBestandId);
const blob = bestand.getBlob();
const response = UrlFetchApp.fetch('https://upload.voorbeeld.nl/bestanden', {
method: 'POST',
payload: {
bestand: blob,
naam: bestand.getName(),
},
});
return JSON.parse(response.getContentText());
}
Retry-patroon bij tijdelijke fouten
Status 429 (te veel verzoeken) en 5xx-fouten zijn meestal tijdelijk. Een korte wachttijd die per poging oploopt, voorkomt dat je de API verder overbelast.
function fetchMetRetry(url, opties = {}, maxPogingen = 3) {
for (let poging = 1; poging <= maxPogingen; poging++) {
try {
const response = UrlFetchApp.fetch(url, {...opties, muteHttpExceptions: true});
const statusCode = response.getResponseCode();
if (statusCode === 429 || statusCode >= 500) {
if (poging === maxPogingen) {
throw new Error(`API-fout na ${maxPogingen} pogingen: ${statusCode}`);
}
Utilities.sleep(poging * 1000);
continue;
}
return response;
} catch (e) {
if (poging === maxPogingen) throw e;
Utilities.sleep(poging * 1000);
}
}
}
Webhook naar Slack sturen
- Maak een Slack Incoming Webhook URL aan in je Slack-workspace.
- Sla de webhook URL op in
PropertiesService.getScriptProperties(). - Roep de URL aan met
UrlFetchApp.fetch(), metmethod: 'POST',contentType: 'application/json'en een JSON-payload zoalsJSON.stringify({text: 'Bericht'}). - Verwerk de response-code:
200is succes, alles anders behandel je als fout.
Hoe stuur ik form-encoded data?
Gebruik contentType: 'application/x-www-form-urlencoded' en geef het payload als object mee. Apps Script serialiseert het object dan automatisch als form-encoded string.
Kan ik HTTPS-certificaten negeren?
Nee, Apps Script valideert altijd SSL-certificaten. Als een API een zelfondertekend certificaat heeft, kun je daar vanuit Apps Script niet mee verbinden.
Wat is het quotum voor UrlFetchApp?
Volgens de officiele quotapagina (gecontroleerd juni 2026) zijn URL Fetch-aanroepen beperkt tot 20.000 per dag voor gewone gmail.com-accounts en 100.000 per dag voor Google Workspace-accounts. De maximale responsgrootte is 50 MB per aanroep. Een aparte UrlFetch-tijdlimiet in minuten per dag bestaat niet meer; wel geldt de algemene uitvoeringslimiet van zes minuten per scriptrun.
Hoe verwerk ik een XML-response?
Gebruik XmlService.parse(response.getContentText()) om XML te parsen. XmlService is een ingebouwde Apps Script-service voor XML-verwerking.
Hoe voorkom ik dat ik mijn quotum opmaakt?
Cache antwoorden met CacheService voor data die niet vaak verandert, bundel onafhankelijke verzoeken met fetchAll en vermijd onnodige herhaalde aanroepen in lussen. Zo blijf je ruim onder de dagelijkse limiet.
UrlFetchApp is de brug tussen Apps Script en de wereld van externe APIs. Combineer het met PropertiesService voor veilige credential-opslag en CacheService om API-aanroepen te minimaliseren.