API Development with nfltr + Postman

Expose your local API to the internet in seconds, test it with Postman from anywhere, and share live endpoints with your team — no deployment required.


Why nfltr + Postman?

Every API developer hits the same wall: your API runs on localhost:3000 but you need to:

nfltr creates a public tunnel to your local port. Postman talks to the public URL exactly as if your API were deployed. Together they give you a production-like API testing workflow without leaving localhost.

┌──────────┐      HTTPS       ┌────────────┐      gRPC       ┌───────────┐       HTTP       ┌─────────────┐
│  Postman  │ ───────────────► │  nfltr.xyz  │ ──────────────► │  nfltr    │ ───────────────► │ Your API    │
│  (cloud)  │                  │  (server)   │                 │  (agent)  │                  │ :3000       │
└──────────┘                  └────────────┘                  └───────────┘                  └─────────────┘

Quick Start

1. Start your local API

Any framework — Express, FastAPI, Gin, Rails, Spring Boot, whatever:

# Example: a Node.js API
node server.js   # listens on port 3000

2. Expose it with nfltr

nfltr http 3000 --share

Output:

nfltr v1.0.x starting
  agent-id:     macbook-pro
  server:       grpc.nfltr.xyz:443 (tls=true)
  health:       :29501
  timeout:      60s
  route:        (default) → http://localhost:3000

nfltr                  v1.0.x
Agent ID               macbook-pro
Forwarding             https://nfltr.xyz/browse/macbook-pro/ → http://localhost:3000

Share URL: https://swift-bay.nfltr.xyz/
Connected — waiting for requests... (press Ctrl+C to stop)

The share URL (https://swift-bay.nfltr.xyz/) is completely public — no API key, no login, no authentication of any kind.

3. Use the share URL in Postman

  1. Open Postman → create a new request
  2. Set the URL to https://swift-bay.nfltr.xyz/api/users
  3. Choose method (GET, POST, PUT, DELETE)
  4. Add body as needed
  5. Click Send
💡 Note: Share URLs change every time you restart the tunnel. For a stable URL across restarts, see the Tips section below.

The request travels through nfltr's server, through the gRPC tunnel to your machine, hits localhost:3000/api/users, and the response flows back to Postman. Latency is typically 20–50 ms for a single hop.


Workflow: Share a Live API with Your Team

When working on an API, you want teammates to test it against your running code — not a stale staging deploy. Share URLs are public — no API key or login needed.

nfltr http 3000 --share

Hand the share URL (e.g., https://swift-bay.nfltr.xyz/) to your teammate. They paste it into Postman as the base URL and test immediately — no VPN, no deploy, no firewall rules.


Workflow: Postman Collection + nfltr Base URL

Use a Postman environment variable for the base URL so you can switch between local, tunnel, and production without editing every request.

Set up the environment

Set the share URL as your base URL — no API key needed:

VariableValue
baseUrlhttps://swift-bay.nfltr.xyz

Use it in requests

GET {{baseUrl}}/api/users
POST {{baseUrl}}/api/orders
PUT {{baseUrl}}/api/orders/{{orderId}}
DELETE {{baseUrl}}/api/users/{{userId}}

When your tunnel changes, update the single variable. All requests adapt.

Switch between environments

EnvironmentbaseUrl
Localhttp://localhost:3000
Tunnel (share)https://swift-bay.nfltr.xyz
Staginghttps://api.staging.example.com
Productionhttps://api.example.com

Workflow: Receive Webhooks in Postman + nfltr

Third-party services (Stripe, GitHub, Twilio, Razorpay) send webhook callbacks to a URL you configure. During development, that URL needs to reach your local machine.

Step 1: Create a webhook endpoint in your API

# FastAPI example
@app.post("/webhooks/stripe")
async def stripe_webhook(request: Request):
    body = await request.body()
    sig = request.headers.get("stripe-signature")
    # verify & process...
    return {"status": "ok"}

Step 2: Expose with nfltr

# Use --share so Stripe can reach your endpoint without an API key
nfltr http 8000 --share

The --share flag is important here: external services like Stripe cannot send an X-API-Key header, so /browse/ URLs won't work for inbound webhooks. The share URL (e.g., https://swift-bay.nfltr.xyz/) is publicly accessible.

Step 3: Configure Stripe dashboard

Set the webhook URL to your share URL (shown in the nfltr output):

https://swift-bay.nfltr.xyz/webhooks/stripe

Step 4: Monitor in Postman

Use Postman's History sidebar to see every webhook that arrived, or create a Postman Monitor that periodically hits your tunnel endpoint to verify it's healthy.

Step 5: Replay webhooks

Stripe and GitHub let you re-send past webhook events from their dashboards. Every replay hits your local code via the nfltr tunnel, letting you debug handler logic in real time.


Workflow: Multi-Backend Routing

Modern apps have multiple services: an API server, a frontend dev server, a WebSocket server. nfltr routes them all through one tunnel:

nfltr http 3000 \
  --route /api=8080 \
  --route /ws=4000 \
  --share

Use the share URL (e.g., https://calm-fox.nfltr.xyz/) in Postman and organize requests into folders: /api/..., /ws/..., root.

Postman requestRouted to
GET https://calm-fox.nfltr.xyz/api/usershttp://localhost:8080/api/users
GET https://calm-fox.nfltr.xyz/ws/connecthttp://localhost:4000/ws/connect
GET https://calm-fox.nfltr.xyz/http://localhost:3000/

Workflow: Run Postman Collections via Newman (CI)

Use Newman to run your Postman collection against a live nfltr tunnel from CI:

# Terminal 1: start your API + tunnel
nfltr http 3000 --share --duration 600 &

# Terminal 2: run the Postman collection (use the share URL from output)
newman run my-collection.json \
  --env-var "baseUrl=https://swift-bay.nfltr.xyz" \
  --reporters cli,junit \
  --reporter-junit-export results.xml

This lets your CI pipeline test the real code running on a developer machine (or a CI runner) through a tunnel — useful for integration tests that need real backends.


Workflow: OAuth Callback Testing

OAuth flows redirect to a callback URL. During development, that callback needs to reach your local server. Use a share URL for the callback — it's publicly accessible, so the OAuth redirect works reliably without any authentication requirements:

nfltr http 3000 --name oauth-dev --share

Output:

Agent ID               alice.oauth-dev
Share URL              https://swift-bay.nfltr.xyz/

Configure your OAuth provider (Google, GitHub, Auth0) with the share URL:

Callback URL: https://swift-bay.nfltr.xyz/oauth/google/callback

The --name flag gives your agent a stable identity across restarts (useful for the /browse/ URL), while --share generates a public URL that works as an OAuth callback without any auth barriers.

Why not use the /browse/ URL for callbacks?
/browse/ URLs require authentication (API key header or active dashboard session) on every request. OAuth redirects are plain browser GETs from the provider — they won't carry your nfltr API key or session cookie. Use --share to get a public URL that works reliably.

The full OAuth flow works end-to-end:

  1. PostmanGET {{baseUrl}}/login → redirects to Google
  2. Google → authenticates → redirects to your share URL callback
  3. nfltr → tunnels callback to localhost:3000/oauth/google/callback
  4. Your API → exchanges code for token → responds

Use Postman's Authorization tab with OAuth 2.0 type for automated token management.

Tip: Share URLs change on each restart. For stable callback URLs across restarts, you'll need to update the provider's callback URL each time you reconnect — or keep the tunnel running with --duration.


Workflow: Load Testing with Postman + nfltr

# Use a share URL for easy access
nfltr http 3000 --share
# Use the share URL from the output as your Postman base URL

In Postman:

  1. Open your collection → Run collection
  2. Set iterations (e.g., 100)
  3. Set delay (e.g., 100ms)
  4. Click Run

nfltr handles concurrent requests through the gRPC tunnel. Monitor your API's response times directly in Postman's run results.


Tips & Best Practices

Use --name for stable URLs (advanced)

nfltr http 3000 --name my-api

With --name my-api, the /browse/ URL stays the same across restarts, which is useful for bookmarked endpoints and personal access from tools that can send an X-API-Key header (like curl or Postman). /browse/ URLs are not suitable for webhooks or OAuth callbacks — external services cannot authenticate.

Your full agent ID is <api-key-prefix>.<name> — for example, if your API key's identity is alice, then --name my-api creates the browse URL /browse/alice.my-api/. Agent IDs are not globally unique — they're scoped to your API key, so different users can safely pick the same --name without conflict. Run nfltr status to see your exact agent ID.

For most Postman workflows, --share is simpler — no auth needed.

Use --share for easy collaboration

nfltr http 3000 --share

Share URLs like https://swift-bay.nfltr.xyz/ expire after the tunnel disconnects — perfect for a code review session or a quick demo. No authentication needed — just share the link.

Set request timeout in Postman

nfltr's default request timeout is 60 seconds. Match it in Postman: Settings → General → Request timeout → 60000 ms.

Use Postman's console for debugging

Open View → Postman Console (⌘+⌥+C) to see raw request/response headers. Useful for verifying nfltr's proxy headers.

Combine with Postman's Mock Server

  1. Build your contract in Postman (mock server)
  2. Implement the real API locally
  3. Expose via nfltr
  4. Swap the Postman environment from mock to tunnel URL
  5. Run the same collection — validates real vs. mock parity

Complete Example: REST API Development Session

# 1. Start your API
cd my-api && go run . &   # serves on :8080

# 2. Create a tunnel with a share URL
nfltr http 8080 --share

# 3. In Postman, set baseUrl to the share URL from the output
#    e.g., baseUrl = https://swift-bay.nfltr.xyz

# 4. Test CRUD operations:
#    POST   {{baseUrl}}/api/users      → Create
#    GET    {{baseUrl}}/api/users       → List
#    GET    {{baseUrl}}/api/users/123   → Read
#    PUT    {{baseUrl}}/api/users/123   → Update
#    DELETE {{baseUrl}}/api/users/123   → Delete

# 5. Share with teammate — just send the share URL

# 6. Configure Stripe webhooks: paste the share URL + path
#    https://swift-bay.nfltr.xyz/webhooks/stripe

# 7. Run full collection:
#    newman run api-tests.json --env-var "baseUrl=https://swift-bay.nfltr.xyz"

# 8. Done — Ctrl+C to stop the tunnel

What You Get in This Workflow

FeatureWhat NFLTR gives you
Stable named URLs--name gives you a durable endpoint identity you can keep in collections and scripts.
Shareable short URLs--share creates a public URL you can hand to teammates or webhook providers.
Multi-route tunnels--route lets one tunnel front several local services.
mTLS authProtected endpoints can use built-in mutual TLS instead of only bearer-style access.
Webhook verificationThe webhook verification module gives you a path from manual Postman tests to signed-provider traffic.
ARM / edge agentsThe same workflow can run on laptops, ARM hosts, and WASM-based environments.

Troubleshooting

"Connection refused" in Postman

Your local API isn't running. Verify:

curl http://localhost:3000/

nfltr tunnels to whatever is listening on the port. If nothing is listening, Postman gets a 502 Bad Gateway.

Slow responses (>1s)

Check the hop count: your machine → nfltr.xyz → your machine. If the server is far away, latency adds up.

nfltr logs every request automatically:

[1] GET /api/users → http://localhost:3000/api/users → 200 (1234 bytes, txn=abc123)
[2] POST /api/orders → http://localhost:3000/api/orders → 201 (88 bytes, txn=def456)

Use --verbose to also log heartbeats and full request headers:

nfltr http 3000 --verbose

"503 Service Unavailable" with Retry-After

The agent was recently connected but is temporarily offline. nfltr returns 503 with a Retry-After: 30 header so Postman retries after 30 seconds. If the agent reconnects in time, the next request succeeds.

CORS errors in Postman

Postman doesn't enforce CORS — that's a browser-only restriction. If you see CORS issues, you're testing from a browser, not Postman. Add CORS headers to your API or use Postman directly.


Next Steps