Skip to main content
HTTP is the only way a function is invoked. Requests arrive at https://<func-name>-<org-nickname>.telnyxcompute.com (see Routing) and are handed to your entrypoint — but what “your entrypoint” means differs by language. In TypeScript and JavaScript you own and run the HTTP server (the CLI scaffolds a working one); in Go, Python, and Java the server is run for you and your code is called per request. telnyx-edge new-func -l <language> generates a working entrypoint for each language. The code on this page is that scaffold — start from it rather than a blank file.

The contract at a glance

LanguageFileYou implementServer owned byHealth probes
TypeScript / JavaScriptindex.ts / index.js (project root)An HTTP server on process.env.PORT || 8080YouYou — return 200 for /health and paths under it
Gohandler.gofunc Handle(w http.ResponseWriter, r *http.Request) in package functionPlatformHandled for you — no health route in your code
Pythonfunction/func.pynew() factory returning an object with async def handle(self, scope, receive, send)PlatformPlatform — probes never reach handle()
Javasrc/main/java/functions/Function.javaA method annotated @Funq (Quarkus Funqy)QuarkusSmallRye Health at /health/*, pre-configured

The scaffold, by language

Each tab is one language’s entrypoint contract and the scaffold new-func generates for it.
You own the server. There is no framework-provided handler(request) entrypoint and no Response object to return — your function is a container running a plain node:http server (or any server framework you install). Two things are contractual:
  • Listen on process.env.PORT, falling back to 8080.
  • Answer /health (and paths under it) with a 200. The platform’s liveness and readiness probes hit it — a function that doesn’t answer isn’t routed traffic and can be restarted. Keep the probe path fast: respond before any other work.
index.ts lives at the project root, next to func.toml — not in src/. The scaffold, lightly condensed (comments trimmed):
import * as http from 'node:http';

interface ResponseData {
  message: string;
  data?: any;
}

const server = http.createServer(async (req: http.IncomingMessage, res: http.ServerResponse) => {
  // Liveness/readiness probes — answer before any other work
  if (req.url === '/health' || req.url?.startsWith('/health/')) { res.writeHead(200); res.end(); return; }

  const responseData: ResponseData = {
    message: 'Hello from Telnyx Edge Compute!'
  };

  // POST: read and echo the request body
  if (req.method === 'POST') {
    let body = '';

    req.on('data', (chunk: Buffer) => {
      body += chunk.toString();
    });

    req.on('end', () => {
      if (body) {
        try {
          responseData.data = JSON.parse(body);
        } catch (error) {
          responseData.data = body;   // not JSON — echo as text
        }
      }

      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify(responseData));
    });
  } else {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify(responseData));
  }
});

const port = process.env.PORT || 8080;
server.listen(port, () => {
  console.log(`Server running on port ${port}`);
});
The JavaScript scaffold (-l js) is the same file minus type annotations, at index.js (same project-root location).Request bodies arrive as data events carrying Buffer chunks. The scaffold accumulates them as a string, which is fine for text and JSON — for binary bodies collect the buffers instead (chunks.push(chunk) then Buffer.concat(chunks)), because toString() corrupts non-UTF-8 bytes.

Bodies, headers, and binary data

These apply to the raw-HTTP contracts — TypeScript, JavaScript, Go, and Python. Java/Funqy is the exception: it’s typed JSON in/out, so raw bodies, binary responses, and custom headers aren’t available from a @Funq method (see the Java tab).
  • Bodies pass through raw, both directions. There is no base64 envelope and no JSON wrapping between the caller and your code. To serve binary, set the Content-Type and write the bytes:
    res.writeHead(200, { "Content-Type": "image/png" });
    res.end(pngBuffer);   // raw bytes — no base64
    
  • Headers are yours. Whatever your server (or Handle, or http.response.start) sets is what the caller receives. There is no platform header rewriting to work around.
  • Bodies are size-capped. Request and response body limits are listed in Limits.

The request budget

A function has 30 seconds by default to respond, and 60 seconds at most. Past the budget the request is terminated and the caller gets a 504. This is a platform limit, not a func.toml field — there is no timeout_seconds setting. For work that can run long, set your own internal timeout a few seconds under the platform’s and return an error or partial result instead of being cut off mid-response. Exact numbers and the other caps — memory, body size, deploy rate — are in Limits.
  • Bindings — the typed env surface: Telnyx API, secrets, KV
  • Execution model — lifecycle, cold starts, concurrency
  • Limits — timeouts, body size, memory