Each example is the inside of main, written in every language API Maker runs : pick yours in the tabs, and every page shows it from then on. The types a call takes (GetAll, DeepItem…) are those of am : from am import GetAll in Python, use am::GetAll; in Rust, import am.GetAll; in Java and Kotlin ; PHP and C# have them without an import, Go names them am.GetAll.
To get the value of request header x-custom-authorization, use g.req.auth.authCustom.
constcustomAuth=g.req.auth.authCustom;// what the token validator returned
custom_auth=g.req.auth.authCustom# what the token validator returned
$customAuth = $g->req->auth->authCustom; // what the token validator returned
varcustomAuth=g.Req.Auth["authCustom"];// what the token validator returned
customAuth:=g.Req.Auth().Get("authCustom")// what the token validator returned
letcustom_auth=&g.req.auth()["authCustom"];// what the token validator returned
ObjectcustomAuth=g.req.getAuth().get("authCustom");// what the token validator returned
valcustomAuth=g.req.auth["authCustom"]// what the token validator returned
Whatever your Token Validator function returns is what lands in g.req.auth.authCustom. Return the decoded JWT payload and you get the decoded token there — return your own object and you get that instead.
AM, database, AWS, Azure and Google cover most cases. But sometimes the token is yours — your own claims, your own signing key, your own expiry rules. That is what a Custom Token Generator is for: you write the code that mints the token and the code that checks it, and API Maker handles the rest of the request pipeline.
Below is a complete working example: a JWT signed with HS256, with the usual JWT package of each language.
Go to Operations → Sandbox Settings, select the language of the provider and add its package (see Packages):
Language
Registry
Package
TypeScript
npm
jose
Python
PyPI
pyjwt
PHP
Packagist
firebase/php-jwt
C#
NuGet
Microsoft.IdentityModel.JsonWebTokens
Go
Go modules
github.com/golang-jwt/jwt/v5
Rust
crates.io
jsonwebtoken[rust_crypto] and uuid[v4]
Java, Kotlin
Maven Central
com.auth0:java-jwt
Once added, it is available in every piece of code of that language, including the two functions below.
Then add a key of your own to the secret, jwtSigningKey, with at least 32 random characters: the packages of PHP and C# refuse a shorter key for HS256. Keep it for the tokens alone. common.secretFETransfer is no signing key: your apps hold it, so anyone with a copy of an app could sign tokens with it.
Go to Security → Auth Providers, click + and pick Custom Token Generator.
You will get three tabs: Basic Info, Token Generator and Token Validator. The Basic Info is always TypeScript, which API Maker runs itself when you save ; the generator and the validator are written in the language you pick for the provider.
import*asTfrom'types';import{SignJWT}from"jose";// Produce and return a token string from the request context.// Runs at token-generation time.asyncfunctionmain(g:T.IAMGlobal){constbody:{role:string,userId:string}=g.req.body;constsigningKey=awaitg.sys.system.getSecret('jwtSigningKey');constsecret=newTextEncoder().encode(signingKey);constaccessToken=awaitnewSignJWT({// set your required datarole:body.role,email:"[email protected]",companyId:"cmp_123",}).setProtectedHeader({alg:"HS256",typ:"JWT",}).setSubject(body.userId).setIssuedAt().setExpirationTime("15m").setJti(crypto.randomUUID()).sign(secret);return{access_token:accessToken,refresh_token:'refresh_token_test',validity:19200};};module.exports=main;
importtimeimportuuidimportjwt# the package pyjwtfromamimportG# Produce and return a token string from the request context.# Runs at token-generation time.asyncdefmain(g:G):body=g.req.bodysigning_key=awaitg.sys.system.get_secret('jwtSigningKey')now=int(time.time())access_token=jwt.encode({# set your required data'role':body.role,'email':'[email protected]','companyId':'cmp_123','sub':body.userId,'iat':now,'exp':now+15*60,'jti':str(uuid.uuid4()),},signing_key,algorithm='HS256',)return{'access_token':access_token,'refresh_token':'refresh_token_test','validity':19200,}
<?phpuseFirebase\JWT\JWT;// Produce and return a token string from the request context.// Runs at token-generation time.functionmain(AmG$g){$body=$g->req->body;$signingKey=$g->sys->system->getSecret('jwtSigningKey');$now=time();$accessToken=JWT::encode([// set your required data'role'=>$body->role,'email'=>'[email protected]','companyId'=>'cmp_123','sub'=>$body->userId,'iat'=>$now,'exp'=>$now+15*60,'jti'=>bin2hex(random_bytes(16)),],$signingKey,'HS256');return['access_token'=>$accessToken,'refresh_token'=>'refresh_token_test','validity'=>19200,];}
usingSystem.Text;usingMicrosoft.IdentityModel.JsonWebTokens;usingMicrosoft.IdentityModel.Tokens;filestaticclassApi{// Produce and return a token string from the request context.// Runs at token-generation time.publicstaticasyncTask<object?>Main(Gg){varbody=g.Req.Body;varsigningKey=(awaitg.Sys.System.GetSecret("jwtSigningKey"))?.GetValue<string>()??"";varaccessToken=newJsonWebTokenHandler().CreateToken(newSecurityTokenDescriptor{// set your required dataClaims=newDictionary<string,object>{["role"]=body.GetString("role")??"",["email"]="[email protected]",["companyId"]="cmp_123",["sub"]=body.GetString("userId")??"",["jti"]=Guid.NewGuid().ToString(),},IssuedAt=DateTime.UtcNow,Expires=DateTime.UtcNow.AddMinutes(15),SigningCredentials=newSigningCredentials(newSymmetricSecurityKey(Encoding.UTF8.GetBytes(signingKey)),SecurityAlgorithms.HmacSha256),});returnnew{access_token=accessToken,refresh_token="refresh_token_test",validity=19200,};}}
packagecodeimport("crypto/rand""encoding/hex""time""apimaker/am""github.com/golang-jwt/jwt/v5")// Produce and return a token string from the request context.// Runs at token-generation time.funcMain(g*am.G)(any,error){body:=g.Req.Body()secret,err:=g.Sys.System.GetSecret("jwtSigningKey")iferr!=nil{returnnil,err}signingKey,_:=secret.(string)jti:=make([]byte,16)if_,err:=rand.Read(jti);err!=nil{returnnil,err}now:=time.Now()accessToken,err:=jwt.NewWithClaims(jwt.SigningMethodHS256,jwt.MapClaims{// set your required data"role":body.String("role"),"email":"[email protected]","companyId":"cmp_123","sub":body.String("userId"),"iat":now.Unix(),"exp":now.Add(15*time.Minute).Unix(),"jti":hex.EncodeToString(jti),}).SignedString([]byte(signingKey))iferr!=nil{returnnil,err}returnam.M{"access_token":accessToken,"refresh_token":"refresh_token_test","validity":19200,},nil}
usestd::time::{SystemTime,UNIX_EPOCH};useam::{Errors,G,Value,json};usejsonwebtoken::{Algorithm,EncodingKey,Header,encode};useuuid::Uuid;// Produce and return a token string from the request context.// Runs at token-generation time.pubfnmain(g:&mutG)->Result<Value,Errors>{letbody=g.req.body().clone();letsigning_key=g.sys.system.get_secret("jwtSigningKey",None)?;letnow=SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();letclaims=json!({// set your required data"role":body["role"],"email":"[email protected]","companyId":"cmp_123","sub":body["userId"],"iat":now,"exp":now+15*60,"jti":Uuid::new_v4().to_string(),});letkey=EncodingKey::from_secret(signing_key.as_str().unwrap_or_default().as_bytes());letaccess_token=encode(&Header::new(Algorithm::HS256),&claims,&key)?;Ok(json!({"access_token":access_token,"refresh_token":"refresh_token_test","validity":19200,}))}
importam.G;importam.JsonObject;importcom.auth0.jwt.JWT;importcom.auth0.jwt.algorithms.Algorithm;importjava.time.Instant;importjava.util.UUID;classApi{// Produce and return a token string from the request context.// Runs at token-generation time.staticObjectmain(Gg){JsonObjectbody=g.req.getBody();StringsigningKey=(String)g.sys.system.getSecret("jwtSigningKey");Instantnow=Instant.now();StringaccessToken=JWT.create()// set your required data.withClaim("role",body.getString("role")).withClaim("email","[email protected]").withClaim("companyId","cmp_123").withSubject(body.getString("userId")).withIssuedAt(now).withExpiresAt(now.plusSeconds(15*60)).withJWTId(UUID.randomUUID().toString()).sign(Algorithm.HMAC256(signingKey));returnJsonObject.of("access_token",accessToken,"refresh_token","refresh_token_test","validity",19200);}}
importam.Gimportcom.auth0.jwt.JWTimportcom.auth0.jwt.algorithms.Algorithmimportjava.time.Instantimportjava.util.UUID// Produce and return a token string from the request context.// Runs at token-generation time.funmain(g:G):Any?{valbody=g.req.bodyvalsigningKey=g.sys.system.getSecret("jwtSigningKey")asStringvalnow=Instant.now()valaccessToken=JWT.create()// set your required data.withClaim("role",body.getString("role")).withClaim("email","[email protected]").withClaim("companyId","cmp_123").withSubject(body.getString("userId")).withIssuedAt(now).withExpiresAt(now.plusSeconds(15*60)).withJWTId(UUID.randomUUID().toString()).sign(Algorithm.HMAC256(signingKey))returnmapOf("access_token"toaccessToken,"refresh_token"to"refresh_token_test","validity"to19200,)}
The whole request body reaches this function as g.req.body, so you decide what your login payload looks like.
import*asTfrom'types';import{jwtVerify}from"jose";// Validate an incoming token. Return a truthy object (usually the decoded payload) to mark valid.// Throw or return null/undefined to mark invalid.asyncfunctionmain(g:T.IAMGlobal){constaccessToken=g.req.body.token;constsigningKey=awaitg.sys.system.getSecret('jwtSigningKey');constsecret=newTextEncoder().encode(signingKey);const{payload}=awaitjwtVerify(accessToken,secret,{algorithms:["HS256"],});returnpayload;// return true; // if truthy value returned, means token is valid.// return false; // if token is not valid// return {}; // You can return some object also and it means token is valid.};module.exports=main;
importjwt# the package pyjwtfromamimportG# Validate an incoming token. Return a truthy object (usually the decoded payload) to mark valid.# Raise or return None to mark invalid.asyncdefmain(g:G):access_token=g.req.body.tokensigning_key=awaitg.sys.system.get_secret('jwtSigningKey')# Raises when the signature or the expiry is wrong.payload=jwt.decode(access_token,signing_key,algorithms=['HS256'])returnpayload
<?phpuseFirebase\JWT\JWT;useFirebase\JWT\Key;// Validate an incoming token. Return a truthy object (usually the decoded payload) to mark valid.// Throw or return null to mark invalid.functionmain(AmG$g){$accessToken=$g->req->body->token;$signingKey=$g->sys->system->getSecret('jwtSigningKey');// Throws when the signature or the expiry is wrong.$payload=JWT::decode($accessToken,newKey($signingKey,'HS256'));return$payload;}
usingSystem.Text;usingMicrosoft.IdentityModel.JsonWebTokens;usingMicrosoft.IdentityModel.Tokens;filestaticclassApi{// Validate an incoming token. Return a truthy object (usually the decoded payload) to mark valid.// Throw or return null to mark invalid.publicstaticasyncTask<object?>Main(Gg){varaccessToken=g.Req.Body.GetString("token");varsigningKey=(awaitg.Sys.System.GetSecret("jwtSigningKey"))?.GetValue<string>()??"";varresult=awaitnewJsonWebTokenHandler().ValidateTokenAsync(accessToken,newTokenValidationParameters{IssuerSigningKey=newSymmetricSecurityKey(Encoding.UTF8.GetBytes(signingKey)),ValidAlgorithms=[SecurityAlgorithms.HmacSha256],ValidateIssuer=false,ValidateAudience=false,});returnresult.IsValid?result.Claims:null;}}
packagecodeimport("apimaker/am""github.com/golang-jwt/jwt/v5")// Validate an incoming token. Return a truthy object (usually the decoded payload) to mark valid.// Return an error or nil to mark invalid.funcMain(g*am.G)(any,error){accessToken:=g.Req.Body().String("token")secret,err:=g.Sys.System.GetSecret("jwtSigningKey")iferr!=nil{returnnil,err}signingKey,_:=secret.(string)// An error when the signature or the expiry is wrong.payload:=jwt.MapClaims{}_,err=jwt.ParseWithClaims(accessToken,payload,func(*jwt.Token)(any,error){return[]byte(signingKey),nil},jwt.WithValidMethods([]string{"HS256"}))iferr!=nil{returnnil,err}returnpayload,nil}
useam::{Errors,G,Value};usejsonwebtoken::{Algorithm,DecodingKey,Validation,decode};// Validate an incoming token. Return a truthy object (usually the decoded payload) to mark valid.// Return an error or null to mark invalid.pubfnmain(g:&mutG)->Result<Value,Errors>{letaccess_token=g.req.body()["token"].as_str().unwrap_or_default().to_owned();letsigning_key=g.sys.system.get_secret("jwtSigningKey",None)?;// An error when the signature or the expiry is wrong.letkey=DecodingKey::from_secret(signing_key.as_str().unwrap_or_default().as_bytes());letpayload=decode::<Value>(&access_token,&key,&Validation::new(Algorithm::HS256))?;Ok(payload.claims)}
importam.G;importam.Json;importcom.auth0.jwt.JWT;importcom.auth0.jwt.algorithms.Algorithm;importjava.nio.charset.StandardCharsets;importjava.util.Base64;classApi{// Validate an incoming token. Return a truthy object (usually the decoded payload) to mark valid.// Throw or return null to mark invalid.staticObjectmain(Gg){StringaccessToken=g.req.getBody().getString("token");StringsigningKey=(String)g.sys.system.getSecret("jwtSigningKey");// Throws when the signature or the expiry is wrong.varverified=JWT.require(Algorithm.HMAC256(signingKey)).build().verify(accessToken);returnJson.parse(newString(Base64.getUrlDecoder().decode(verified.getPayload()),StandardCharsets.UTF_8));}}
importam.Gimportam.Jsonimportcom.auth0.jwt.JWTimportcom.auth0.jwt.algorithms.Algorithmimportjava.util.Base64// Validate an incoming token. Return a truthy object (usually the decoded payload) to mark valid.// Throw or return null to mark invalid.funmain(g:G):Any?{valaccessToken=g.req.body.getString("token")valsigningKey=g.sys.system.getSecret("jwtSigningKey")asString// Throws when the signature or the expiry is wrong.valverified=JWT.require(Algorithm.HMAC256(signingKey)).build().verify(accessToken)returnJson.parse(String(Base64.getUrlDecoder().decode(verified.payload)))}
The rule is simple — truthy means valid. Anything falsy, or a thrown error, means the request is rejected.
By the time your code runs, the token is already verified — API Maker rejects bad ones before they reach you. So g.req.auth.authCustom is safe to trust.