Stay organized with collectionsSave and categorize content based on your preferences.
TheCloud Functions for Firebaseclient SDKs let you call functions directly from
a Firebase app. To call a function from your app in this way, write and deploy
an HTTP Callable function inCloud Functions, and
then add client logic to call the function from your app.
It's important to keep in mind that HTTP callable functions are similar butnot identical toHTTP functions. To use HTTP callable functions you must
use the client SDK for your platform together with the
backend API (or implement the protocol). Callables have these key
difference from HTTP functions:
With callables,Firebase Authenticationtokens,FCMtokens, andApp Checktokens, when available, are automatically included in requests.
The trigger automatically deserializes the request body and validates auth tokens.
TheFirebaseSDK forCloud Functions2nd gen and higher interoperates with these Firebase client
SDK minimum versions to support HTTPS Callable functions:
FirebaseSDK forAppleplatforms 12.2.0
FirebaseSDK forAndroid22.0.0
Firebase Modular Web SDK v. 9.7.0
If you want to add similar functionality to an app built on an unsupported
platform, see theProtocol Specification forhttps.onCall. The rest of this guide provides
instructions on how to write, deploy, and call
an HTTP callable function for Apple platforms, Android, web, C++, and Unity.
Write and deploy the callable function
Code examples in this section are based on a completequickstart samplethat demonstrates how to send requests to a server-side function and get a
response using one of the Client SDKs. To get started, import the required
modules:
Node.js
// Dependencies for callable functions.const{onCall,HttpsError}=require("firebase-functions/v2/https");const{logger}=require("firebase-functions/v2");// Dependencies for the addMessage function.const{getDatabase}=require("firebase-admin/database");constsanitizer=require("./sanitizer");
# Dependencies for callable functions.fromfirebase_functionsimporthttps_fn,options# Dependencies for writing to Realtime Database.fromfirebase_adminimportdb,initialize_app
Use the request handler for your platform (functions.https.onCall)
oron_call)
to create an HTTPS callable function. This method
takes a request parameter:
Node.js
// Saves a message to the Firebase Realtime Database but sanitizes the// text by removing swearwords.exports.addmessage=onCall((request)=>{// ...});
@https_fn.on_call()defaddmessage(req:https_fn.CallableRequest)->Any:"""Saves a message to the Firebase Realtime Database but sanitizes the textby removing swear words."""
Therequestparameter contains data passed from the client app as well as additional context like authentication state. For a callable function that saves a text message to theRealtime Database,
for example,datacould contain the message text, along with auth information
inauth:
Node.js
// Message text passed from the client.consttext=request.data.text;// Authentication / user information is automatically added to the request.constuid=request.auth.uid;constname=request.auth.token.name||null;constpicture=request.auth.token.picture||null;constemail=request.auth.token.email||null;
# Authentication / user information is automatically added to the request.uid=req.auth.uidname=req.auth.token.get("name","")picture=req.auth.token.get("picture","")email=req.auth.token.get("email","")
Distance between the location of the callable function and the location
of the calling client can create network latency. To optimize performance,
consider specifying thefunction locationwhere
applicable, and make sure to align the callable's location with the location
set when youinitialize the SDKon the client side.
Optionally, you can attach anApp Checkattestation to help protect your
backend resources from abuse, such as billing fraud or phishing. SeeEnableApp Checkenforcement forCloud Functions.
Send back the result
To send data back to the client, return data that can be JSON encoded. For
example, to return the result of an addition operation:
The sanitized text from the message text example is returned both to the client and to theRealtime Database. In Node.js, this can be done
asynchronously using a JavaScript promise:
Node.js
// Saving the new message to the Realtime Database.constsanitizedMessage=sanitizer.sanitizeText(text);// Sanitize message.returngetDatabase().ref("/messages").push({text:sanitizedMessage,author:{uid,name,picture,email},}).then(()=>{logger.info("New Message written");// Returning the sanitized message to the client.return{text:sanitizedMessage};})
# Saving the new message to the Realtime Database.sanitized_message=sanitize_text(text)# Sanitize message.db.reference("/messages").push({# type: ignore"text":sanitized_message,"author":{"uid":uid,"name":name,"picture":picture,"email":email}})print("New message written")# Returning the sanitized message to the client.return{"text":sanitized_message}
Callable functions have mechanisms for handling streaming results. If you have a
use case that requires streaming, you can configure streaming in the callable
request and then use the appropriate method from the client SDK to call the
function.
Send streaming results
To efficiently stream results that are generated over time, such as from a
number of separate API requests or a generative AI API, check theacceptsStreamingproperty on your callable request. When this property is set
totrue, you can stream results back to the client withresponse.sendChunk().
For example, if an app needed to retrieve weather forecast data for multiple
locations, the callable function could send each location's forecast separately
to clients that have requested a streaming response, instead of making them wait
until all forecast requests have resolved:
exports.getForecast=onCall(async(request,response)=>{if(request.data?.locations?.length<1){thrownewHttpsError("invalid-argument","Missing locations to forecast");}// fetch forecast data for all requested locationsconstallRequests=request.data.locations.map(async({latitude,longitude})=>{constforecast=awaitweatherForecastApi(latitude,longitude);constresult={latitude,longitude,forecast};// clients that support streaming will have each// forecast streamed to them as they completeif(request.acceptsStreaming){response.sendChunk(result);}returnresult;},);// Return the full set of data to all clientsreturnPromise.all(allRequests);});
Note that the wayresponse.sendChunk()operates depends on certain details of
the client's request:
If the client requests a streaming response:response.sendChunk(data)sends the data piece immediately.
If the client does not request a streaming response:response.sendChunk()does nothing for that call. The full response is sent once all data is ready.
To determine whether the client is requesting a streaming response, check therequest.acceptsStreamingproperty. For example, ifrequest.acceptsStreamingis false, you might decide to skip any resource-intensive work specifically
related to preparing or sending individual chunks, as the client isn't expecting
an incremental delivery.
Receive streaming results
In a typical scenario, the client requests streaming with the.streammethod
and then iterates through the results:
// Get the callable by passing an initialized functions SDK.constgetForecast=httpsCallable(functions,"getForecast");// Call the function with the `.stream()` method to start streaming.const{stream,data}=awaitgetForecast.stream({locations:favoriteLocations,});// The `stream` async iterable returned by `.stream()`// will yield a new value every time the callable// function calls `sendChunk()`.forawait(constforecastDataChunkofstream){// update the UI every time a new chunk is received// from the callable functionupdateUi(forecastDataChunk);}// The `data` promise resolves when the callable// function completes.constallWeatherForecasts=awaitdata;finalizeUi(allWeatherForecasts);
Loop through thestreamasync iterable as shown. Awaiting thedatapromise indicates to the client that the request is complete
Kotlin
// Get the callable by passing an initialized functions SDK.valgetForecast=functions.getHttpsCallable("getForecast");// Call the function with the `.stream()` method and convert it to a flowgetForecast.stream(mapOf("locations"tofavoriteLocations)).asFlow().collect{response->when(response){isStreamResponse.Message->{// The flow will emit a [StreamResponse.Message] value every time the// callable function calls `sendChunk()`.valforecastDataChunk=response.message.dataasMap<String,Any>// Update the UI every time a new chunk is received// from the callable functionupdateUI(forecastDataChunk["latitude"]asDouble,forecastDataChunk["longitude"]asDouble,forecastDataChunk["forecast"]asDouble,)}isStreamResponse.Result->{// The flow will emit a [StreamResponse.Result] value when the// callable function completes.valallWeatherForecasts=response.result.dataasList<Map<String,Any>>finalizeUI(allWeatherForecasts)}}}
In order to use theasFlow()extension function, add theorg.jetbrains.kotlinx:kotlinx-coroutines-reactivelibrary as a
dependency to the app'sbuild.gradle(.kts)file.
Java
// Get the callable by passing an initialized functions SDK.HttpsCallableReferencegetForecast=mFunctions.getHttpsCallable("getForecast");getForecast.stream(newHashMap<String,Object>(){{
put("locations", favoriteLocations);
}}).subscribe(newSubscriber<StreamResponse>(){@OverridepublicvoidonSubscribe(Subscriptionsubscription){subscription.request(Long.MAX_VALUE);}@OverridepublicvoidonNext(StreamResponsestreamResponse){if(streamResponseinstanceofStreamResponse.Message){// The flow will emit a [StreamResponse.Message] value every time the// callable function calls `sendChunk()`.StreamResponse.Messageresponse=(StreamResponse.Message)streamResponse;Map<String,Object>forecastDataChunk=(Map<String,Object>)response.getMessage().getData();// Update the UI every time a new chunk is received// from the callable functionupdateUI((double)forecastDataChunk.get("latitude"),(double)forecastDataChunk.get("longitude"),(double)forecastDataChunk.get("forecast"));}elseif(streamResponseinstanceofStreamResponse.Result){// The flow will emit a [StreamResponse.Result] value when the// callable function completes.StreamResponse.Resultresponse=(StreamResponse.Result)streamResponse;List<Map<String,Object>>allWeatherForecasts=(List<Map<String,Object>>)response.getResult().getData();finalizeUI();}}@OverridepublicvoidonError(Throwablethrowable){// an error occurred in the function}@OverridepublicvoidonComplete(){}});
Use thecorsoption to control which origins can access your function.
By default, callable functions have CORS configured to allow requests from all
origins. To allow some cross-origin requests, but not all, pass a list of
specific domains or regular expressions that should be allowed. For example:
To forbid cross-origin requests, set thecorspolicy tofalse.
Handle errors
To ensure the client gets useful error details, return errors from a callable
by throwing (or for Node.js returning a Promise rejected with) an instance offunctions.https.HttpsErrororhttps_fn.HttpsError.
The error has acodeattribute that can be one of the values listed in gRPCStatus codes.
The errors also have a stringmessage, which defaults
to an empty string. They can also have an optionaldetailsfield with an
arbitrary value. If an error other than an HTTPS error is thrown from your functions,
your client instead receives an error with the messageINTERNALand the codeinternal.
For example, a function could throw data validation and authentication errors
with error messages to return to the calling client:
Node.js
// Checking attribute.if(!(typeoftext==="string")||text.length===0){// Throwing an HttpsError so that the client gets the error details.thrownewHttpsError("invalid-argument","The function must be called "+"with one arguments \"text\" containing the message text to add.");}// Checking that the user is authenticated.if(!request.auth){// Throwing an HttpsError so that the client gets the error details.thrownewHttpsError("failed-precondition","The function must be "+"called while authenticated.");}
# Checking attribute.ifnotisinstance(text,str)orlen(text)<1:# Throwing an HttpsError so that the client gets the error details.raisehttps_fn.HttpsError(code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT,message=('The function must be called with one argument, "text",'" containing the message text to add."))# Checking that the user is authenticated.ifreq.authisNone:# Throwing an HttpsError so that the client gets the error details.raisehttps_fn.HttpsError(code=https_fn.FunctionsErrorCode.FAILED_PRECONDITION,message="The function must be called while authenticated.")
After you save a completed callable function withinindex.js, it
is deployed along with all other functions when you runfirebase deploy.
To deploy only the callable, use the--onlyargument as shown to performpartial deploys:
firebase deploy --only functions:addMessage
If you encounter permissions errors when deploying functions, make sure that
the appropriateIAM rolesare
assigned to the user running the deployment commands.
Set up your client development environment
Make sure you meet any prerequisites, then add the required dependencies and
client libraries to your app.
In yourmodule (app-level) Gradle file(usually<project>/<app-module>/build.gradle.ktsor<project>/<app-module>/build.gradle),
add the dependency for theCloud Functionslibrary for Android. We recommend using theFirebase Android BoMto control library versioning.
dependencies{// Import theBoMfor the Firebase platformimplementation(platform("com.google.firebase:firebase-bom:34.2.0"))// Add the dependency for theCloud Functionslibrary// When using theBoM, you don't specify versions in Firebase library dependenciesimplementation("com.google.firebase:firebase-functions")}
By using theFirebase Android BoM,
your app will always use compatible versions of Firebase Android libraries.
(Alternative)
Add Firebase library dependencies without using theBoM
If you choose not to use theFirebase BoM, you must specify each Firebase library version
in its dependency line.
Note that if you usemultipleFirebase libraries in your app, we strongly
recommend using theBoMto manage library versions, which ensures that all versions are
compatible.
dependencies{// Add the dependency for theCloud Functionslibrary// When NOT using theBoM, you must specify versions in Firebase library dependenciesimplementation("com.google.firebase:firebase-functions:22.0.0")}
privatefunaddMessage(text:String):Task<String>{// Create the arguments to the callable function.valdata=hashMapOf("text"totext,"push"totrue,)returnfunctions.getHttpsCallable("addMessage").call(data).continueWith{task->// This continuation runs on either success or failure, but if the task// has failed then result will throw an Exception which will be// propagated down.valresult=task.result?.dataasStringresult}}
privateTask<String>addMessage(Stringtext){// Create the arguments to the callable function.Map<String,Object>data=newHashMap<>();data.put("text",text);data.put("push",true);returnmFunctions.getHttpsCallable("addMessage").call(data).continueWith(newContinuation<HttpsCallableResult,String>(){@OverridepublicStringthen(@NonNullTask<HttpsCallableResult>task)throwsException{// This continuation runs on either success or failure, but if the task// has failed then getResult() will throw an Exception which will be// propagated down.Stringresult=(String)task.getResult().getData();returnresult;}});}
firebase::Future<firebase::functions::HttpsCallableResult>AddMessage(conststd::string&text){// Create the arguments to the callable function.firebase::Variantdata=firebase::Variant::EmptyMap();data.map()["text"]=firebase::Variant(text);data.map()["push"]=true;// Call the function and add a callback for the result.firebase::functions::HttpsCallableReferencedoSomething=functions->GetHttpsCallable("addMessage");returndoSomething.Call(data);}
Unity
privateTask<string>addMessage(stringtext){// Create the arguments to the callable function.vardata=newDictionary<string,object>();data["text"]=text;data["push"]=true;// Call the function and extract the operation from the result.varfunction=functions.GetHttpsCallable("addMessage");returnfunction.CallAsync(data).ContinueWith((task)=>{return(string)task.Result.Data;});}
Handle errors on the client
The client receives an error if the server threw an error or if the
resulting promise was rejected.
If the error returned by the function is of typefunction.https.HttpsError,
then the client receives the errorcode,message, anddetailsfrom the
server error. Otherwise, the error contains the messageINTERNALand the
codeINTERNAL. See guidance for how tohandle errorsin your callable function.
voidOnAddMessageCallback(constfirebase::Future<firebase::functions::HttpsCallableResult>&future){if(future.error()!=firebase::functions::kErrorNone){// Function error code, will be kErrorInternal if the failure was not// handled properly in the function call.autocode=static_cast<firebase::functions::Error>(future.error());// Display the error in the UI.DisplayError(code,future.error_message());return;}constfirebase::functions::HttpsCallableResult*result=future.result();firebase::Variantdata=result->data();// This will assert if the result returned from the function wasn't a string.std::stringmessage=data.string_value();// Display the result in the UI.DisplayResult(message);}// ...// ...autofuture=AddMessage(message);future.OnCompletion(OnAddMessageCallback);// ...
Unity
addMessage(text).ContinueWith((task)=>{if(task.IsFaulted){foreach(varinnerintask.Exception.InnerExceptions){if(innerisFunctionsException){vare=(FunctionsException)inner;// Function error code, will be INTERNAL if the failure// was not handled properly in the function call.varcode=e.ErrorCode;varmessage=e.ErrorMessage;}}}else{stringresult=task.Result;}});
Recommended: Prevent abuse withApp Check
Before you launch your app, you should enableApp Checkto help ensure that only your apps can access your callable function endpoints.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-05 UTC."],[],[],null,[]]