UrlFetchApp supports POST, PUT, PATCH, and DELETE requests. You set the method, contentType, and payload options to send structured data — JSON, form data, or raw strings — to any external API endpoint.
Basic POST Request with a JSON Body
function basicPostRequest() {
var url = "https://httpbin.org/post";
var payload = JSON.stringify({
customerName: "Sarah Johnson",
product: "Pro Plan",
amount: 299
});
var options = {
method: "POST",
contentType: "application/json",
payload: payload,
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(url, options);
Logger.log("Status: " + response.getResponseCode());
Logger.log("Response: " + response.getContentText());
}Posting a Closed Deal to a CRM API
This example reads each newly closed deal from the Sales Tracker and POSTs it to a CRM:
function syncClosedDealsToCRM() {
var sheet = SpreadsheetApp
.getActiveSpreadsheet()
.getSheetByName("Sales Tracker");
var data = sheet.getRange(2, 1, sheet.getLastRow() - 1, 9).getValues();
// Columns: [Customer Name, Email, Product, Amount, Region, Sales Rep, Status, Date, CRM Synced]
var apiUrl = "https://api.your-crm.com/v1/deals";
var apiToken = "YOUR_API_TOKEN";
data.forEach(function(row, i) {
var customerName = row[0];
var email = row[1];
var product = row[2];
var amount = row[3];
var region = row[4];
var salesRep = row[5];
var status = row[6];
var dealDate = row[7];
var synced = row[8];
if (status !== "Closed" || synced === "Synced") return;
var payload = JSON.stringify({
contact: { name: customerName, email: email },
deal: {
title: customerName + " – " + product,
value: amount,
currency: "USD",
stage: "won",
region: region,
owner: salesRep,
close_date: Utilities.formatDate(new Date(dealDate), Session.getScriptTimeZone(), "yyyy-MM-dd")
}
});
var options = {
method: "POST",
contentType: "application/json",
headers: { "Authorization": "Bearer " + apiToken },
payload: payload,
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(apiUrl, options);
if (response.getResponseCode() === 201) {
sheet.getRange(i + 2, 9).setValue("Synced");
Logger.log("Synced to CRM: " + customerName);
} else {
Logger.log("Failed for " + customerName + ": " + response.getResponseCode());
}
Utilities.sleep(200);
});
}Sending a PUT Request to Update a Record
function updateDealInCRM(dealId, newStatus) {
var url = "https://api.your-crm.com/v1/deals/" + dealId;
var payload = JSON.stringify({ stage: newStatus });
var options = {
method: "PUT",
contentType: "application/json",
headers: { "Authorization": "Bearer YOUR_API_TOKEN" },
payload: payload,
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(url, options);
Logger.log("Update status: " + response.getResponseCode());
}Sending Form-Encoded Data
Some APIs (like older REST endpoints or OAuth flows) require application/x-www-form-urlencoded data:
function postFormData() {
var url = "https://httpbin.org/post";
var options = {
method: "POST",
payload: {
customer: "Mark Chen",
product: "Enterprise Plan",
amount: "999"
}
// Apps Script auto-sets content type to application/x-www-form-urlencoded
};
var response = UrlFetchApp.fetch(url, options);
Logger.log(response.getContentText());
}Handling the POST Response
function handlePostResponse(response) {
var code = response.getResponseCode();
if (code === 200 || code === 201) {
var result = JSON.parse(response.getContentText());
Logger.log("Success. Created ID: " + result.id);
return result;
} else if (code === 400) {
Logger.log("Bad request – check your payload.");
} else if (code === 401 || code === 403) {
Logger.log("Auth error – check your API key.");
} else if (code === 429) {
Logger.log("Rate limited – slow down requests.");
} else {
Logger.log("Error " + code + ": " + response.getContentText());
}
return null;
}