Add KYC to your product without building a KYC screen: verification links, an iframe and webhooks
#api — Public Fediverse posts
Live and recent posts from across the Fediverse tagged #api, aggregated by home.social.
-
Most teams that need to check who a customer is end up building the same thing: a page that asks for...#api #webdev #security #javascript #software #coding #development #engineering #inclusive #community
Add KYC to your product without building a KYC screen: verification links, an iframe and webhooks -
If you are building a product for Nigerian users, KYC conversations start with two eleven-digit...#api #fintech #africa #beginners #software #coding #development #engineering #inclusive #community
NIN vs BVN: what Nigerian identity numbers are, and which one to verify in your app -
One run, two inputs, the same amount of speech. Fetching audio out of a social video page was 82% of the bill and transcription was 16% — plus what a recognition segment does to your caption file once the speaker stops talking in bursts.#python #api #video #webscraping #software #coding #development #engineering #inclusive #community
Subtitling a 65-Second TikTok Cost $0.11. The Same Minute as a File Cost $0.011 -
If your product ships as an iOS app, an Android app and a Chrome extension, its reviews sit in three...#webscraping #python #api #productmanagement #software #coding #development #engineering #inclusive #community
How to scrape App Store, Google Play and Chrome Web Store reviews in one run -
I recently worked on a project called APIWatch using Python and WSO2 API Manager. It is a small...#api #backend #monitoring #python #software #coding #development #engineering #inclusive #community
APIWatch: Checking API Traffic and Subscription Controls with WSO2 API Manager -
Introducing OpenFeed 🇪🇺
An EU-run social network with an open JSON API. Our own app is live, and anyone can build theirs on the same network.
• Public feed, open spaces, invite-only private spaces
• EU company, EU hosting, no ads, no profiling
• One account for every app built on itPublic beta is live. Claim your handle:
Building apps? The API is open, come build with us.
#OpenFeed #DigitalSovereignty #BuyEuropean #EUTech #Privacy #SocialMedia #API
-
https://www.europesays.com/se/424908/ YouTube-kommentarer får stöd för bilder och GIF:ar i november #animationer #API #BärbarDator #bilder #feedback #Gemenskap #GIF:ar #Google #kommentarer #kreatörer #laptop #Medlemskap #Mobil #moderering #notebook #Science #ScienceAndTechnology #ScienceAndTechnology #SE #Shorts #Svenska #Sverige #Sweden #Swedish #Technology #Teknik #uppdateringar #utrullning #Vetenskap #VetenskapTeknik #YouTube
-
Introducing OpenFeed 🇪🇺
An EU-run social network with an open JSON API. Our own app is live, and anyone can build theirs on the same network.
• Public feed, open spaces, invite-only private spaces
• EU company, EU hosting, no ads, no profiling
• One account for every app built on itPublic beta is live. Claim your handle:
Building apps? The API is open, come build with us.
#OpenFeed #DigitalSovereignty #BuyEuropean #EUTech #Privacy #SocialMedia #API
-
Why does a truncated model answer look exactly like a finished one when the only thing you check is the HTTP status code?
That question cost me most of a weekend. I had wired a small summarizer to a streaming endpoint, watched it print a paragraph, and shipped it. Two days of field notes later, I had learned that "HTTP 200" tells you nothing about whether the answer actually completed, and that my parser was happily reporting success on streams that never sent a terminator.
Here is what I tried, what broke, and the probe harness I now run before trusting any streaming endpoint.
The symptom: a paragraph that stopped mid-thought
In my run, the response body ended cleanly at the socket level, the status line said 200, and my client wrote whatever it had buffered. Nothing raised. The output simply stopped mid-sentence, which readers interpret as a model being terse rather than a transport being over. Because I was printing tokens as they arrived, I never compared what I received against what the protocol promised me.That is the trap with streaming: the happy path and the failure path share the same first N bytes. If you only assert on status codes and on the existence of output, both paths pass.
What I instrumented instead of what I assumed
I stopped eyeballing output and wrote a probe that records protocol facts rather than vibes. It reads the response line by line, assembles SSE frames, and records four things per request: time to first byte, whether afinish_reasonappeared in any JSON payload, whether the[DONE]sentinel arrived, and how the socket ended.# stream_probe.py — stdlib only, so it runs anywhere
import json, sys, time, urllib.requestdef parse_frame(lines):
"""SSE frames are newline-delimited; data may span several lines."""
payload =
[] for line in lines:
if line.startswith(":"):
continue # comment / keep-alive
if line.startswith("data:"):
payload.append(line[5:].lstrip(" "))
if not payload:
return None, False
joined = "\n".join(payload).strip()
if joined == "[DONE]":
return None, True
try:
return json.loads(joined), False
except json.JSONDecodeError:
return {"_unparsed": joined}, Falsedef find_finish_reason(obj):
if isinstance(obj, dict):
if obj.get("finish_reason"):
return obj["finish_reason"]
for v in obj.values():
hit = find_finish_reason(v)
if hit:
return hit
elif isinstance(obj, list):
for v in obj:
hit = find_finish_reason(v)
if hit:
return hit
return Nonedef probe(url, payload, headers, read_timeout):
rec = {"ttfb_s": None, "frames": 0, "finish_reason": None,
"done_sentinel": False, "unparsed_frames": 0, "error": None}
req = urllib.request.Request(
url, data=json.dumps(payload).encode(), headers=headers, method="POST")
started = time.monotonic()
frame_lines =
[] try:
with urllib.request.urlopen(req, timeout=read_timeout) as resp:
for raw in resp:
if rec["ttfb_s"] is None:
rec["ttfb_s"] = round(time.monotonic() - started, 3)
line = raw.decode("utf-8", "replace").rstrip("\r\n")
if line:
frame_lines.append(line)
continue
obj, done = parse_frame(frame_lines)
frame_lines =
[] if done:
rec["done_sentinel"] = True
if obj is not None:
rec["frames"] += 1
if "_unparsed" in obj:
rec["unparsed_frames"] += 1
else:
rec["finish_reason"] = rec["finish_reason"] or find_finish_reason(obj)
except Exception as exc: # read timeouts land here on purpose
rec["error"] = f"{type(exc).__name__}: {exc}"
rec["elapsed_s"] = round(time.monotonic() - started, 3)
return recif __name__ == "__main__":
url = sys.argv
[1] body = json.loads(sys.argv[2])
hdrs = json.loads(sys.argv[3])
print(json.dumps(probe(url, body, hdrs, read_timeout=20.0), indent=2))Then a soak loop, because one clean request proves almost nothing:
for i in $(seq 1 20); do
python stream_probe.py "$URL" "$BODY" "$HEADERS" | jq -c '{ttfb_s,frames,finish_reason,done_sentinel,unparsed_frames,error}'
done | tee soak.jsonl
jq -s 'group_by(.finish_reason) | map({reason: .[0].finish_reason, n: length})' soak.jsonlThe four endings the harness separates
Once I classified results instead of staring at them, the ambiguity collapsed into a small set of observable outcomes:- Clean finish. A
finish_reasonarrived and[DONE]followed it, so the answer is complete and my parser can trust the buffer. - Reason without sentinel. The payload carried a
finish_reasonbut the stream closed before[DONE], which suggests a proxy that buffers or cuts the tail frame. - Sentinel without reason.
[DONE]arrived early, which usually means the server truncated generation server-side and reported nothing useful about why. - Neither. The socket closed with a partial sentence and no metadata, which is the case that burned me, and the only honest response is to mark the answer as incomplete and retry or surface it to the caller.
Only case one deserves a green check. Everything else should set an
incompleteflag on the record you store, because a truncated summary that silently enters your database is worse than a visible error.Where a free server and free models actually fit
I run this probe from a throwaway box precisely because I want the transport to be the boring part. MonkeyCode offers free model access and a free server option, which makes it a reasonable place to park a short soak loop like the one above while you are still deciding whether an endpoint deserves production traffic.Disclosure: This article was prepared as part of MonkeyCode's product outreach.
The important discipline is not to treat "free" as "verified". Whatever endpoint you point the probe at, read that provider's current limits and terms yourself on the day you run it, because quotas, model availability, and server lifetimes change and any number I copied here would be stale by the time you read it.
A decision table I now keep in the repo
Signal from the probeWhat I do nextfinish_reasonplus[DONE]on 20/20 runsWire it into the pipeline and keep the probe as a canaryOccasional missing[DONE], reason presentParse per frame, tolerate the tail, log a counterFrequent missingfinish_reasonTreat every response as untrusted text, never as finalRead timeouts clustered at a fixed secondSuspect an idle proxy timeout, not model slownessunparsed_framesabove zeroFix framing first; never debug content on a broken parserWhat I would repeat and what I would skip
I would repeat the soak loop and the classification, because those two together turned a spooky intermittent bug into a checklist. I would skip the hours I spent reading model output for clues about whether the generation was "good", since the transport was broken the whole time and no amount of reading prose would have revealed that.I would also repeat running the probe from a machine I do not care about. Wrapping the read in a hard timeout and letting exceptions land in the record, rather than crashing the loop, is what made the soak results readable.
Limitations and who should not bother
This workflow is for streaming text responses over SSE; if your SDK already exposes a completion flag you trust, a hand-rolled probe is mostly redundant. It also cannot tell you why a provider cut a stream, only that the frames disagree with each other, so pair it with the provider's own logs when you escalate. And if your workload is batch and non-streaming, a single content-length check will beat all of this.If you keep one habit from these field notes, make it this: assert on the terminator, not on the status code. A stream that never says goodbye is not a finished answer, no matter how confident the first paragraph looks.#python #api #debugging #testing #software #coding #development #engineering #inclusive #community
48-Hour Field Notes: My Stream Ended Without [DONE] and the Client Called It Success - Clean finish. A
-
One Set of Listings, Two Front Ends: Planning a Real Estate App with Flutter and the WordPress REST API#flutter #wordpress #mobile #api #software #coding #development #engineering #inclusive #community
One Set of Listings, Two Front Ends: Planning a Real Estate App with Flutter and the WordPress REST API -
Mapbox is hiring Software Development Engineer II, Maps Search
🔧 #cplusplus #rust #typescript #api
🌎 Tokyo, Japan
⏰ Full-time
🏢 MapboxJob details https://jobsfordevelopers.com/jobs/software-development-engineer-ii-maps-search-at-mapbox-com-apr-15-2024-2f90c8?utm_source=mastodon.world&utm_medium=social&utm_campaign=posting
#jobalert #jobsearch #hiring -
AI tools are becoming increasingly capable, but there's still a gap between what AI can do and what...#ai #mcp #api #test #software #coding #development #engineering #inclusive #community
From API to MCP to Skills: Making AI Integrations Easier for Everyone -
RT @cheatyyyy: DeepSeek hat seine eigene Suchmaschine mit umfangreicher Filterung entwickelt, um modernes SEO/GEO-Spam zu vermeiden, und speist damit seine neuen Such- und Fetch-APIs! Jede API kostet $0,75 pro 1.000 erfolgreiche Anfragen, kostenlos wenn Sie DeepSeek in Claude Code, Codex oder DeepSeek Harness nutzen bis November 1.
mehr auf Arint.info
#API #DeepSeek #KünstlicheIntelligenz #SEO #Suchmaschine #Technologie #arint_info
-
Found in my Snaps: MoroccoAPI. From the GitHub page: “MoroccoAPI is a community-driven, open-source project that turns reusable Moroccan public datasets into consistent, documented, and versioned APIs. Public information is often distributed across spreadsheets, documents, portals, and incompatible schemas. MoroccoAPI aims to make approved open datasets easier to discover and use while […]
https://rbfirehose.com/2026/10/18/informational-datasets-gathered-in-one-place-moroccoapi/ -
Many desktop AI tools ship provider keys to the client. Here's why Cernalo keeps them server-side, how requests are routed with fallbacks, and what that costs.#ai #security #architecture #api #software #coding #development #engineering #inclusive #community
Why Our AI Desktop Assistant Never Stores Model API Keys on Your Computer -
🌐 Want to build a killer social wall? With the Walls.io API, pull posts from EVERY platform and style 'em your way! 💻✨ Are you ready to take your feed to the next level? 👉 https://blog.walls.io/product/how-to-build-a-social-wall-with-the-walls-io-social-media-api/ #SocialMedia #API #WebDev
-
MCP vs API explained with real tests: same service as REST and MCP, 76 µs vs 424 µs per call, 14x throughput gap, and what tool definitions cost in tokens.#mcp #ai #api #webdev #software #coding #development #engineering #inclusive #community
MCP vs API: When You Need Which, With Real Benchmarks -
A beginner-friendly guide to fetch(), async/await, response.ok, timeouts, and JSON parsing, with working examples and the mistakes that trip people up.#javascript #webdev #beginners #api #software #coding #development #engineering #inclusive #community
How to Call an API with JavaScript fetch() and Handle Errors Properly -
We probed 68 live x402 endpoints on Base to answer one question: can a stock buyer client actually pay this? Results, failure classes, and a runnable checklist for your own endpoint.#ai #api #crypto #webdev #software #coding #development #engineering #inclusive #community
What 68 x402 endpoints taught us about agent-payability -
Disclosure: I build TubeText. This post uses our Video Breakdown AI Actor on Apify. The output below...#ai #api #youtube #contentcreation #software #coding #development #engineering #inclusive #community
Reverse-engineer a creator's style: an AI persona and style guide from their latest videos -
ive been maintaining this small opensource project GLM Proxy (glmproxy on npm) for a while and its...#api #javascript #node #opensource #software #coding #development #engineering #inclusive #community
Using AutoClaws free GLM models usage from other sdks (opencode / claude code) -
Stop Blaming the Model: A Failure-Taxonomy Probe for Agent Runs on Free Tiers
Your agent died at 2 a.m. Was the model bad? Probably not.Most failed runs I see are misattributed. The model gets blamed for transport, quota, or a bad contract check.
Here is a short myth-busting FAQ. It ends with one probe that sorts failures into five layers.
Myth 1: A 200 response means the request worked
A status code describes transport only. It says nothing about usable output.You can get 200 with
finish_reason: "length". You can get 200 with a refusal. You can get 200 with JSON that parses but misses a required field.Is that a successful unit of work? No. It is a received but rejected artifact.
So define acceptance in code. Parse it, validate it, hash it. Otherwise you are counting receipts, not results.
Myth 2: Retries are free
Retries are cheap on the network side. They are expensive on the side-effect side.Retry a read and nothing changes. Retry a tool call that writes a row and now you have two rows.
That is not a model problem. That is a missing idempotency key.
My rule: every attempt carries a stable
Idempotency-Key. Derive it from the task id, never from the attempt counter.Myth 3: Latency numbers tell you which model to pick
Median latency answers one narrow question. How fast is a warm path?That is rarely your user's path. Free-tier hosts often show two clusters: warm and cold.
Measure time-to-accepted-artifact instead. That number includes your retries and your validator.
Two models with identical token speed can land far apart here. One simply fails validation more often.
Myth 4: A bad run means a bad model
Attribute before you switch vendors. Ask which layer failed, not which model.- Transport: timeout, DNS failure, connection reset.
- Quota: 429, 402, or an explicit rate-limit body.
- Contract: schema mismatch, truncation, refusal, empty content.
- Tool: your function raised, or returned junk.
- Task: the prompt asked for something impossible.
Only the last two are usually your prompt's fault. The contract layer is often your own validator.
The probe: one script, five layers
This script uses the Python standard library only. It records enough to classify every attempt.I have not run it against your endpoint. Treat any output as illustrative, not as a benchmark.
# probe.py - failure-taxonomy probe (illustrative, unexecuted here)
import json, os, time, urllib.request, urllib.error, hashlibBASE = os.environ["BASE_URL"] # OpenAI-compatible base, e.g. https://host/v1
MODEL = os.environ["MODEL"]
KEY = os.environ.get("API_KEY", "")
RUNS = int(os.environ.get("RUNS", "8"))
PROMPT = os.environ.get("PROMPT", 'Return JSON: {"ok": true}')def call(idem):
body = json.dumps({
"model": MODEL,
"messages": [{"role": "user", "content": PROMPT}],
"temperature": 0,
"max_tokens": 256,
}).encode()
url = BASE.rstrip("/") + "/chat/completions"
req = urllib.request.Request(url, data=body, method="POST")
req.add_header("Content-Type", "application/json")
req.add_header("Idempotency-Key", idem)
if KEY:
req.add_header("Authorization", "Bearer " + KEY)
t0 = time.monotonic()
try:
with urllib.request.urlopen(req, timeout=120) as r:
return r.status, r.read(), (time.monotonic() - t0) * 1000, ""
except urllib.error.HTTPError as e:
return e.code, e.read(), (time.monotonic() - t0) * 1000, "http_error"
except Exception as e:
return None, b"", (time.monotonic() - t0) * 1000, type(e).__name__def classify(status, schema_ok):
if status is None: return "transport"
if status == 429: return "quota"
if status in (401, 403): return "auth"
if status and status >= 500: return "upstream"
if status != 200: return "contract"
if not schema_ok: return "contract"
return "ok"task_id = os.environ.get("TASK_ID", "probe-1")
ledger =[]for attempt in range(1, RUNS + 1):
idem = task_id # stable across retries, on purpose
status, raw, ms, err = call(idem)
schema_ok, reason = False, ""
try:
payload = json.loads(raw.decode() or "{}")
choice = payload["choices"]
[0] reason = choice.get("finish_reason", "")
json.loads(choice["message"]["content"]) # your real contract check goes here
schema_ok = True
except Exception as e:
reason = reason or type(e).__name__
ledger.append({
"attempt": attempt, "idem": idem, "status": status,
"ms": round(ms), "bytes": len(raw), "finish": reason,
"err": err,
"sha256": hashlib.sha256(raw).hexdigest()[:12],
"layer": classify(status, schema_ok),
})for row in ledger:
print(json.dumps(row))print("--- layer histogram ---")
for layer in sorted({r["layer"] for r in ledger}):
print(layer, sum(1 for r in ledger if r["layer"] == layer))Run it with three environment variables and a repeat count:
BASE_URL=https://your-endpoint/v1 MODEL=your-model RUNS=12 python3 probe.py
The ledger is the whole point. One row equals one attempt with one label.
How to read the ledger
- Many
contractrows withfinish: "length"? Raise the output budget, or shrink the ask. transportrows at fixed intervals? Suspect an idle timeout, not the model.quotamixed withok? You need pacing, not a new vendor.- Identical
sha256values attemperature: 0? Cache them, do not re-run. - Zero
okrows and clean transport? Your contract check is probably wrong.
Does reading the labels change your conclusion? It usually changes mine.
A decision table you can argue with
Dominant layerFirst fixDo not dotransporttimeout plus backoffprompt tuningquotaconcurrency cap, queuea second accountcontractschema, budget, validatorvendor switchingtoolidempotency, typed errorsa longer prompttaskrewrite the askmore retries
Keep this table next to the script. It ends the "which model is best" debate quickly.The debugging workflow, in order
- Reproduce with
RUNS=1and a fixed prompt. - Read the response body, not just the status.
- Log
finish_reasonand output byte count. - Replace my contract check with your real one.
- Re-run with
RUNS=12and read the histogram. - Fix only the top layer. Then measure again.
- Keep the ledger as a regression fixture.
Steps five and six get skipped all the time. That is where the time is saved.
Where a free tier actually fits
I would run this probe before trusting any free endpoint with a batch job.That is the useful part of free model access plus a free server option. You get a place to run the probe before provisioning anything.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
MonkeyCode lists free model access and a free server option. Those two claims are operator-supplied, and I am not extending them.
I will not guess at model names, quota, hardware, or duration. Measure those with the script above, then decide.
Use the free tier for the probe and the small jobs. Keep the layer table honest either way.
Limitations, and who should skip this
- The script assumes an OpenAI-compatible chat endpoint. Yours may not be.
- It does not test concurrency. Add a parallel runner if that is your risk.
- It cannot prove a tier stays free. Re-run it on a schedule instead.
- It says nothing about output quality. That needs a separate eval.
- The
Idempotency-Keyheader only helps if your server honors it.
Skip this if you already trace each attempt with layer labels. Skip it for a single one-off call.
Also skip it if you need throughput guarantees today. A probe measures, it does not promise.
The question I would ask first
Next time an agent run fails, ask: which layer failed? Not: which model should I try?Write the layer into your logs and your error messages. The argument gets shorter every time.#ai #testing #python #api #software #coding #development #engineering #inclusive #community
Stop Blaming the Model: A Failure-Taxonomy Probe for Agent Runs on Free Tiers -
A 402 response is not just a price. In the
extensions.bazaarblock it can also carry an input example and an output example — a sample request and a sample answer. Directory crawlers index them, and agents use them to decide whether an endpoint does what they need before they pay.That makes an example a claim. If the sample answer disagrees with what the handler actually returns, the agent has three bad options: conclude the endpoint is broken, conclude the platform is lying, or spend money to find out. None of those are good, and all of them are avoidable if the example is true.
We replayed ours to see how many were.
Method
For every service with a published output example (1,602 of them — one endpoint's correct answer is an empty set and was excluded from this population), we took the published input, sent it to the handler that serves it over loopback, and compared the real response against the advertised example with a recursive key-subset check. Arrays are compared strictly; nested objects allow the response to carry extra keys but not to drop an advertised one.Comparing once is not enough, because a large share of endpoints are supposed to vary: prices, block heights, AI text, random values. A disagreement there is not a defect. So every mismatch was replayed two more times with the same input. If the three real responses were byte-identical and still disagreed with the example, that is a stable difference — the kind a user would hit every single time.
Results
BucketCountMeaningMATCH1,444example equals the responseVARYING141the response itself changes run to runSTABLE-DIFF17same response every time, still disagreesEXEMPT8a field that is a timestamp by definition
The 17 stable differences broke down cleanly:- 9 time-derived. "Days since 2026-01-01" was 284 when the example was captured and 289 when it was replayed. "Days remaining" on a certificate only moves one way. These examples are snapshots and will drift every day.
- 7 upstream data that changes daily or hourly. FX rates, funding-rate windows, news feeds, prediction-market volumes, a live bounty list.
- 1 real defect. An endpoint that returns DNS record sets was advertising one ordering of the A records and, half the time, serving the other.
The defect: the DNS resolver round-robins
Ask a resolver the same question twice and you get the same set of records in a different order. That is normal DNS behaviour. It becomes a bug the moment a handler passes the array through unchanged while the 402 advertises a fixed ordering: an agent that calls twice and diffs the answers sees a change that never happened, and an agent that pattern-matches against the example is told its correct answer is wrong.The fix is small — sort at the boundary, one shared helper, no field added:
const { sortDns } = require('../lib/dnssort');
// ...
result[tt] = sortDns(records.map(format));Same record set, one deterministic answer. We verified it by calling the same endpoint four times and comparing response bytes: identical.
The more interesting mistake was ours
That was not the first pass. An earlier sweep had already found the ordering problem in 18 other handlers and fixed them. This one was missed — and the reason is worth writing down, because it is a mistake that looks like success.The fix population had been drawn from that day's mismatch report: whichever endpoints happened to disagree with their example were inspected, and the ones with the same signature were fixed. But the ordering cycles. On the day of the sweep, the resolver happened to return the A records in the same order the example advertised. So the endpoint did not appear in the mismatch report, was not in the fix population, and kept the defect — while every guard printed clean.
A defect population drawn from the sample that happened to fail is not the population. The population is every object that can have the defect.
The correct population is source-derived: every deployed handler that requires DNS and calls.resolve*()or.reverse(). That is 21 files here, not 18, and it is derived mechanically instead of from a bucket of symptoms. The same pass also caught a handler that joined TXT records before anyone looked at their order.We now run that census daily against the deployed bytes. It enforces three things: every DNS-serving handler must sort, self-sort, or reduce the array to a scalar; a handler not on the table is a failure; and a table row with no matching handler is also a failure, because a policy row that nothing enforces is worse than no row at all.
What this does and does not fix
The 17 stable differences were not all bugs, and we did not "fix" them by deleting the examples. Volatile endpoints still advertise a snapshot — that is the honest thing to publish, and the directory expects a sample. What changed is that we now know exactly which examples are snapshots and which are claims, and a replayed sample that contradicts its handler is a red light rather than a shrug.The one real defect is fixed. The population it hid in is now enumerated from source and checked every day.
All numbers in this post are from a single replay run on 2026-10-17 against the deployed handler bytes; the method and per-endpoint buckets are in the repository's artifacts directory.#ai #webdev #crypto #api #software #coding #development #engineering #inclusive #community
Your Discovery Example Is a Promise — We Replayed 1,602 of Ours to Check -
Every Shopify store publishes its catalogue as JSON, and the obvious freshness field in it is the wrong one. Four stores measured on 17 October 2026 show published_at inflating a dead catalogue into 404 fresh products.#webscraping #ecommerce #api #node #software #coding #development #engineering #inclusive #community
398 of 692 Products Were Published in One Afternoon. Zero Were Created in 90 Days -
Data from a daily scan of 50,000 paid x402 and MPP endpoints - 93% payable, one seller holds 41%, Base carries 97%, the median price is $0.01, and the most common seller mistakes with their fixes.#x402 #ai #api #webdev #software #coding #development #engineering #inclusive #community
We check 50,000 paid x402 endpoints every day. Here's what works and what breaks. -
When you answer someone's question on a forum, the date of the post tells you less than you think.
A founder told me their replies stopped working after day 5 to 7. By then the person has picked a tool or moved on, and your answer lands in an empty room.
A better signal: did the author reply to anyone in their own thread in the last 24 hours? If yes, they're still reading. Your answer gets seen today.
Three platforms give you that for free, without a key: DEV, Hacker News and Discourse forums. Here's the whole thing, about 40 lines of Node 18+.
The shared part
Every platform returns replies as a tree. Normalize each one to { author, at, children }, then walk it:// Latest reply written by
authoranywhere in the tree (ms), or null.
function lastReplyBy(nodes, author) {
let last = null;
const walk = (items) => {
for (const n of items) {
if (n.author?.toLowerCase() === author.toLowerCase() && n.at > (last ?? 0)) last = n.at;
walk(n.children);
}
};
walk(nodes);
return last;
}const isAlive = (at, hours = 24) => at !== null && Date.now() - at <= hours * 3_600_000;
DEV
The article endpoint gives you the id, the comments endpoint gives you the full tree:async function devto(user, slug) {
const article = await (await fetch(https://dev.to/api/articles/${user}/${slug})).json();
const raw = await (await fetch(https://dev.to/api/comments?a_id=${article.id})).json();
const map = (cs) =>
cs.map((c) => ({ author: c.user?.username, at: Date.parse(c.created_at), children: map(c.children ?? []) }));
return lastReplyBy(map(raw), user);
}
Hacker News
The Algolia API returns the whole thread in one call. Times are in seconds, and deleted comments have no author (the ?. above handles that):async function hn(id) {
const item = await (await fetch(https://hn.algolia.com/api/v1/items/${id})).json();
const map = (cs) =>
cs.map((c) => ({ author: c.author, at: c.created_at_i * 1000, children: map(c.children ?? []) }));
return lastReplyBy(map(item.children ?? []), item.author);
}
Discourse forums
A lot of product communities run on Discourse. Add .json to a topic URL and you get a flat list where the first post is the question itself:async function discourse(host, topicId) {
const t = await (await fetch(https://${host}/t/${topicId}.json)).json();
const posts = t.post_stream.posts;
const replies = posts.slice(1).map((p) => ({ author: p.username, at: Date.parse(p.created_at), children: [] }));
return lastReplyBy(replies, posts[0].username);
}
One limit: on long topics, that JSON only includes the first batch of posts (20 by default).Using it
const at = await hn(50131997);
console.log(isAlive(at) ? "author still replying" : "probably moved on");
Reddit has the same kind of tree in .json, but it often blocks requests coming from servers, so I left it out.Why I built this
I'm building FounderPulse, which finds people who just posted about the problem your product solves. A post asking for exactly what you sell is worth a lot more when its author is still in the thread, so live threads now move to the top of the list. If you want to see what it finds for your product, there's a free test at founder-pulse.com, no signup.What signal do you use to decide a thread is still worth answering?#javascript #webdev #api #showdev #software #coding #development #engineering #inclusive #community
Is anyone still reading that thread? Check the author's last reply with 3 free APIs -
Your retry loop is maybe eight lines. Why does it double your bill and duplicate side effects?
I keep seeing the same pattern in reviews. The retry logic looks correct, and everyone stops reading there.
That is the problem. Retries are where cost, correctness, and latency quietly disagree.
Below are five claims I hear often, the evidence that breaks them, and a small drill you can run in an afternoon.
Label: the code here is a template, not a benchmark. I have not run it against your stack. Run the drill yourself and trust your own numbers, not mine.
Myth 1: "A retry is basically free"
A retry is not a repeat. It is a second request with the same input.You pay to send the prompt again, on every attempt. Long system prompts make this expensive fast.
Corrected model: retry cost scales with
input_tokens × attempts × concurrent_callers. Measure attempts, not errors.Ask yourself: does your dashboard count attempts, or only final outcomes? Most count outcomes.
Myth 2: "HTTP 200 means the model finished"
A 200 means the transport succeeded. It says nothing about the answer.Truncated completions, empty content, and stream cuts all arrive as 200. Your retry loop never fires.
Corrected model: treat
finish_reason, content length, and schema validity as part of the success check. A response is not a result.How many of your retries are actually triggered by business-level incompleteness? Usually zero.
Myth 3: "Exponential backoff with jitter is enough"
Backoff controls timing. It does not control volume.If every caller retries four times, a partial outage becomes a full one. Jitter spreads the pain, not the load.
Corrected model: add a retry budget per request and per minute. Cap total attempts across the fleet.
Rules that survive contact with production:
- Retry
429and5xxonly. Never retry400or401. - Honor
Retry-Afterwhen present. It beats your formula. - Stop after a fixed attempt count. Then fail over or fail closed.
- Emit one metric per attempt, tagged by error class.
Myth 4: "Retrying is idempotent because the call is stateless"
The model call is stateless. Your handler is not.If the tool call wrote a ticket, charged a card, or sent mail, a retry repeats the side effect.
Corrected model: retries are only safe behind an idempotency key or a commit barrier. The barrier is a local check: did the side effect already happen?
Rhetorical but useful: what would your retry loop do to a payment webhook twice in a row?
Myth 5: "You can resume a stream where it stopped"
You cannot resume mid-token. The connection is gone, and so is the partial state.What you can do is checkpoint at message boundaries. Re-request with the completed prefix as context.
Corrected model: streams are not resumable transports. They are progress signals. Persist what you received, then decide.
The drill: inject faults, count attempts
This is the part that changes minds. Ten minutes of setup, one table of evidence.The stub server uses only the standard library. No dependencies, no keys.
# stub_server.py - deterministic fault injection, Python 3.9+
import json, threading
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServerFAULTS = ["ok", "truncate", "500", "429", "slow"]
state = {"n": 0}
lock = threading.Lock()class H(BaseHTTPRequestHandler):
def do_POST(self):
self.rfile.read(int(self.headers.get("Content-Length", 0)))
with lock:
fault = FAULTS[state["n"] % len(FAULTS)]
state["n"] += 1
if fault == "500":
self.send_response(500); self.end_headers()
self.wfile.write(b'{"error":"boom"}'); return
if fault == "429":
self.send_response(429)
self.send_header("Retry-After", "1"); self.end_headers(); return
body = {"choices": [{
"message": {"role": "assistant", "content": "ok"},
"finish_reason": "length" if fault == "truncate" else "stop",
}]}
raw = json.dumps(body).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(raw)))
self.end_headers()
self.wfile.write(raw)
def log_message(self, *args):
passif __name__ == "__main__":
ThreadingHTTPServer(("127.0.0.1", 8787), H).serve_forever()Now the client. It records every attempt in a ledger.
# drill.py - counts attempts and re-sent input per call
import json, random, time, urllib.error, urllib.requestURL = "http://127.0.0.1:8787/v1/chat"
PROMPT = "summarise this ticket in one line" # swap for a real payloaddef classify(code, body):
if code == 429:
return "throttle"
if code >= 500 or code == 0:
return "transient"
if code == 200 and body["choices"][0]["finish_reason"] == "length":
return "truncated"
return "ok"def call_once():
req = urllib.request.Request(
URL,
data=json.dumps({"prompt": PROMPT}).encode(),
headers={"Content-Type": "application/json"},
)
try:
with urllib.request.urlopen(req, timeout=5) as r:
return r.status, json.loads(r.read())
except urllib.error.HTTPError as e:
return e.code, {}
except Exception:
return 0, {}def drill(cases=10, budget=4):
ledger =
[] for _ in range(cases):
input_tokens = len(PROMPT.split()) # crude proxy, use real usage
for attempt in range(1, budget + 1):
code, body = call_once()
cls = classify(code, body)
ledger.append({"attempt": attempt, "code": code,
"class": cls, "input_resent": input_tokens})
if cls in ("ok", "truncated"):
break
delay = min(2 ** attempt * 0.1, 1.0)
time.sleep(delay * random.uniform(0.5, 1.5))
return ledgerif __name__ == "__main__":
rows = drill()
print(json.dumps(rows, indent=2))
print("attempts:", len(rows))
print("input tokens re-sent:", sum(r["input_resent"] for r in rows))Run it:
python stub_server.py &
python drill.py | tail -n 2Then read the ledger. Do you see attempts your old loop would have skipped? Do you see truncated responses marked as success?
The decision table I actually use
SignalRetry?Action429withRetry-AfterOnceSleep the header value, then one attempt5xxYes, budgetedBackoff with jitter, cap at 3Timeout, no responseYes, budgetedSame route first, then failover400/401NeverFix the request or the credentialfinish_reason = lengthNoRaise the limit or chunk the inputEmpty contentOnceRetry, then fail closedWhere MonkeyCode fits in this drill
A fault drill needs two things: a stub server and a second route to fail over to.MonkeyCode's free model access gives me that second route without a card. The operator-supplied free server option can host the stub, so the drill does not touch production networking.
I would not run the whole harness blindly there. Check the current quotas and limits yourself first.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
Use it as the failover target you test against, not as the reason the drill exists. The drill works with any second endpoint.
Limitations, and who should skip this
- The stub returns fixed shapes. It tests your control flow, not model quality.
- Token counts in the script are a proxy. Swap in real usage numbers.
- Retry budgets need tuning per route. One global number hides the problem.
Skip this if you have a single caller and no side effects. You have bigger wins elsewhere.
Skip it too if your platform already enforces retry budgets and idempotency keys. Audit those settings instead.
What changes after the drill
You stop treating retries as error handling. You start treating them as load, cost, and duplicate-work decisions.That reframing is the whole payoff. The eight-line loop stays short, but now it has a reason for every line.
What would your ledger show tomorrow?#ai #testing #python #api #software #coding #development #engineering #inclusive #community
Five Myths About Retrying an LLM Call, and the Fault-Injection Drill That Tests Them - Retry
-
📢 New #updates · 17 Oct #14
· Wallos v5.10.0 — Bulk toolbar improvements and fixes
· TrailBase v0.35.0 — Faster inserts, transactional file writes, and batch insert behavior change
· mirrord 3.275.0 — Added Helm chart support and Kafka branch isolation
· UniFi-Poller v5.6.0 — Improved station counts and SSD cache exportsAll updates live on https://selfhost.directory
-
Casino API Integration Explained: Architecture, Wallet Callbacks, and Scaling an iGaming Platform#igaming #casino #slots #api #software #coding #development #engineering #inclusive #community
Casino API Integration Explained: Architecture, Wallet Callbacks, and Scaling an iGaming Platform -
How I designed the API layer for Trify3D — a platform that routes one input across multiple AI 3D...#webdev #ai #api #showdev #software #coding #development #engineering #inclusive #community
Building a Multi-Engine 3D Generation API: Routing, Credits, and Webhooks -
Security Tip: Stop hardcoding API keys in your source code! 🛡️ Hardcoded secrets in version control are a primary vector for account takeovers. Use environment variables or secrets management vaults like HashiCorp Vault or AWS Secrets Manager. Implement a regular rotation policy—automated if possible—to reduce the blast radius of a leaked credential. Stay ahead of vulnerabilities at https://cvedatabase.com #InfoSec #CyberSecurity #API #DevSecOps #AppSec
-
Kwetter heet vanaf nu OpenFeed 🎉
OpenFeed wordt één Europees sociaal netwerk met een volledig open API, vastgelegd in een openbare OpenAPI 3.1-spec. Apps bouwen hun eigen interface, OpenFeed draait het netwerk. Eén account werkt in elke app.
Op openfeed.eu komt onze eigen app, op precies dezelfde API.
✅ EU-bedrijf, EU-hosting
✅ Geen advertenties, geen profilering
✅ Geen tracking tussen apps -
私は APIGOTO チームで働いています。APIGOTO は独立したサービスで、OpenAI・Anthropic・Google とは提携関係にありません。
APIGOTO は OpenAI 互換の LLM API ゲートウェイです。
・base_url は https://api.china-aiapi.com/v1 の1つだけで Claude / GPT / Gemini を呼び出せます
・上流エラー時は自動フェイルオーバー(リトライは最大3回まで)
・リクエストごとのログ
・BYOK(自分のプロバイダーキーを持ち込み可)
・従量課金
質問です:リトライ上限3回は既定値として妥当でしょうか?それともリクエストごとに変えられた方がいいですか?
www.china-aiapi.com
#LLM #API #プログラミング -
私は APIGOTO チームで働いています。APIGOTO は独立したサービスで、OpenAI・Anthropic・Google とは提携関係にありません。
APIGOTO は OpenAI 互換の LLM API ゲートウェイです。
・base_url は https://api.china-aiapi.com/v1 の1つだけで Claude / GPT / Gemini を呼び出せます
・上流エラー時は自動フェイルオーバー(リトライは最大3回まで)
・リクエストごとのログ
・BYOK(自分のプロバイダーキーを持ち込み可)
・従量課金
質問です:LLM 呼び出しのデバッグで、ログのどの項目(レイテンシ、トークン数、応答した上流、リトライ履歴など)を実際に見ていますか?
www.china-aiapi.com
#LLM #API #プログラミング -
私は APIGOTO チームで働いています。APIGOTO は独立したサービスで、OpenAI・Anthropic・Google とは提携関係にありません。
APIGOTO は OpenAI 互換の LLM API ゲートウェイです。
・base_url は https://api.china-aiapi.com/v1 の1つだけで Claude / GPT / Gemini を呼び出せます
・上流エラー時は自動フェイルオーバー(リトライは最大3回まで)
・リクエストごとのログ
・BYOK(自分のプロバイダーキーを持ち込み可)
・従量課金
質問です:BYOK で自分のキーが上限に達したとき、黙って別経路に切り替えるのと、明示的にエラーにするのと、どちらが良いですか?
www.china-aiapi.com
#LLM #API #プログラミング -
私は APIGOTO チームで働いています。APIGOTO は独立したサービスで、OpenAI・Anthropic・Google とは提携関係にありません。
APIGOTO は OpenAI 互換の LLM API ゲートウェイです。
・base_url は https://api.china-aiapi.com/v1 の1つだけで Claude / GPT / Gemini を呼び出せます
・上流エラー時は自動フェイルオーバー(リトライは最大3回まで)
・リクエストごとのログ
・BYOK(自分のプロバイダーキーを持ち込み可)
・従量課金
質問です:リトライ上限3回は既定値として妥当でしょうか?それともリクエストごとに変えられた方がいいですか?
www.china-aiapi.com
#LLM #API #プログラミング -
私は APIGOTO チームで働いています。APIGOTO は独立したサービスで、OpenAI・Anthropic・Google とは提携関係にありません。
APIGOTO は OpenAI 互換の LLM API ゲートウェイです。
・base_url は https://api.china-aiapi.com/v1 の1つだけで Claude / GPT / Gemini を呼び出せます
・上流エラー時は自動フェイルオーバー(リトライは最大3回まで)
・リクエストごとのログ
・BYOK(自分のプロバイダーキーを持ち込み可)
・従量課金
質問です:LLM 呼び出しのデバッグで、ログのどの項目(レイテンシ、トークン数、応答した上流、リトライ履歴など)を実際に見ていますか?
www.china-aiapi.com
#LLM #API #プログラミング -
A registry record, two DNS witnesses and a comps table: why a single availability check lies, with working code for .si.#dns #api #webdev #python #software #coding #development #engineering #inclusive #community
Checking ccTLD availability without trusting one source (and what .si actually sells for) -
An 855 · Purchase Order Acknowledgment is the seller's business answer to an 850 · Purchase Order:...#edi #api #integration #supplychain #software #coding #development #engineering #inclusive #community
The EDI 855, Decoded: The Purchase Order Acknowledgment Is Where the Order Becomes a Promise -
📢 New #updates · 17 Oct #10
· Pi-hole v6.5 — Security fixes for command execution and root privilege escalation
· Firefly III develop-20261017.3 — Latest fixes translations and features
· Dawarich 1.16.0 — Added supporter badge and address support for visits
· lightdash 2.602.0 — Tool titles now visible in annotationsMore self-hosted updates → https://selfhost.directory
-
Cloudflare is hiring Principal Software Engineer, Workers Deploy & Config
🔧 #cplusplus #golang #javascript #rust #typescript #react #api #graphql #kubernetes #principalengineer
🌎 In-Office
⏰ Full-time
🏢 CloudflareJob details https://jobsfordevelopers.com/jobs/principal-software-engineer-workers-deploy-config-at-cloudflare-com-aug-6-2026-32ae55?utm_source=mastodon.world&utm_medium=social&utm_campaign=posting
#jobalert #jobsearch #hiring -
🚀 New #release · cState v7-r1
- cState v7-r1 prerelease for testing, v6.0.2 remains stable.
- Modern default skin, classic skin retained.
- Experiments, releases, changelog, roadmap, evals, decisions, research with JSON/RSS/Atom feeds.
- Reporting web component with Markdown export and GitHub/GitLab handoff.Check and self-host it → https://selfhost.directory/project/cstate#update-22270147
-
Many Claude Code gateway failures are diagnosed too late. People often change the model name first,...#debugging #claudecode #api #software #coding #development #engineering #inclusive #community
Claude Code API Gateways on Windows: Verify Base URL and Authentication Before Debugging Models -
A decimal separator parsing bug charged $10,000 instead of $100, exposing critical gaps in agent billing infrastructure and locale-aware validation.#api #architecture #backend #security #software #coding #development #engineering #inclusive #community
Anthropic's 100 Overcharge Bug: What Internationalization Failures Reveal About Agent Payment Pipelines -
📢 New #updates · 17 Oct #8
· Ghostfolio 3.87.0 — Added investment chart story and improved performance timeline chart
· Ever Gauzy v111.108.0 — Inbox email handling now more reliable
· lightdash 2.601.0 — Claude plugin integration added
· SWAG (Secure Web Application Gateway) 5.8.0-ls490Browse everything at https://selfhost.directory
-
A census of x402 endpoints is only as good as the request it sends. Send the wrong one and a...#api #backend #mcp #software #coding #development #engineering #inclusive #community
How a GET probe makes working x402 endpoints look broken -
Instagram does not make it easy to watch other public accounts. Most follower trackers need your...#instagram #api #automation #webscraping #software #coding #development #engineering #inclusive #community
I built a no-login Instagram follower tracker that only shows what changed since the last run -
私は APIGOTO チームで働いています。APIGOTO は独立したサービスで、OpenAI・Anthropic・Google とは提携関係にありません。
APIGOTO は OpenAI 互換の LLM API ゲートウェイです。
・base_url は https://api.apigoto.com/v1 の1つだけで Claude / GPT / Gemini を呼び出せます
・上流エラー時は自動フェイルオーバー(リトライは最大3回まで)
・リクエストごとのログ
・BYOK(自分のプロバイダーキーを持ち込み可)
・従量課金
質問です:429(レート制限)のときも 5xx と同じようにフェイルオーバーすべきでしょうか?それとも同じプロバイダーでバックオフすべきでしょうか?
www.china-aiapi.com
#LLM #API #プログラミング -
I work on the APIGOTO team. APIGOTO is independent and not affiliated with OpenAI, Anthropic or Google.
APIGOTO is an OpenAI-compatible LLM gateway: one base_url https://api.apigoto.com/v1 for Claude, GPT and Gemini, automatic failover capped at 3 retries, per-request logs, BYOK, pay-per-use.
Question: is a fixed cap of 3 retries a sensible default, or should it be configurable per request?
www.china-aiapi.com
#LLM #API #DevTools