今日已更新 84 条资讯 | 累计 37333 条内容
关于我们

标签:#API

找到 517 篇相关文章

AI 资讯

Building a Chatbot Taught Me About LLM APIs

Most people's first experience with an LLM API is deceptively simple: send a prompt, get a reply. It feels like magic, and for a single question-answer exchange, it basically is. But the moment you try to build something that holds an actual conversation one where the model remembers what you said three messages ago you run into a problem that isn't obvious until you hit it: LLM APIs are stateless. Every request is a blank slate unless you explicitly hand the model its own memory. That was the core challenge behind a recent project I built during my internship a chatbot backed by a real LLM API ([OpenAI / Gemini]) with genuine multi-turn conversation support, not just a scripted request-response loop. * The problem nobody mentions upfront * You can't just "turn on" memory. Every conversation turn has to be manually tracked and resent with each new API call, which means the developer, not the model, is responsible for deciding what counts as context. And that decision has real consequences: send too little history and the bot forgets things it should remember; send too much, and you run into token limits and rising costs as the conversation grows. This is where most simple chatbot tutorials stop short. They show you how to get a reply from an API, but not what happens once a conversation runs long enough that you can't keep resending everything forever. * Where the actual engineering happens * Solving that meant implementing a context management strategy deciding what to keep, what to drop, and eventually exploring smarter approaches like summarising older parts of a conversation instead of just discarding them. It also meant thinking about the bot's identity through a system prompt, handling API failures gracefully instead of letting the UI break, and treating credentials properly by keeping API keys out of source code entirely. None of this is complicated in isolation. What's interesting is how much of it is invisible until you actually build the thing yourself. Us

2026-08-22 原文 →
AI 资讯

I built an OLX scraper for 24 countries — the boring version that actually ships

I built an OLX scraper for 24 countries — the boring version that actually ships OLX runs classifieds in about two dozen countries. Same brand, different domains, different anti-bot setups. Everyone scraping it does one country at a time. I got tired of forking. So I put 24 countries behind one input. country: "id" or country: "pl" or country: "br" — same schema out. It's live on Apify as primesieve/olx-global-scraper . One file. No browser. Here is the boring part that matters. What it does Input: { "country" : "id" , "keywords" : [ "iphone 13" ], "maxResults" : 50 , "maxPages" : 3 , "proxyConfiguration" : { "useApifyProxy" : true , "apifyProxyGroups" : [ "RESIDENTIAL" ] } } country — two-letter code ( id , pl , in , br , ua , pt , ro , bg , kz , uz , pk , za , ng , ke , eg , lb , ph , co , ar , pe , ec , gt , az , ma ). Default id . keywords — one or more search terms. Each runs sequentially. maxResults / maxPages — caps. Defaults 50 / 3, max 1000 / 30. proxyConfiguration — optional for Indonesia, required for the other 23. Output — same shape every country: { "listingId" : "123456789" , "title" : "iPhone 13 128GB mulus" , "price" : 6500000 , "priceText" : "Rp 6.500.000" , "currency" : "IDR" , "city" : "Jakarta Selatan" , "location" : "Tebet, Jakarta Selatan, DKI Jakarta" , "images" : [ "https://...jpg" ], "thumbnailUrl" : "https://...jpg" , "listingUrl" : "https://www.olx.co.id/item/123456789" , "country" : "id" } Title, price (numeric plus display text), currency, location, images, URL. No seller PII beyond what the listing page shows. No tricks. Try: https://apify.com/primesieve/olx-global-scraper The boring stack // no playwright, no puppeteer // apify + fetch + cheerio. That's it. The scraper is one file. Apify SDK for input, dataset, and pay-per-event. Native fetch for HTTP. cheerio for the HTML path. Undici ProxyAgent when a proxy is configured. Node 20, 512 MB, 600s timeout. I check the endpoint before I write the scraper. Indonesia answered with clean JSO

2026-08-22 原文 →
AI 资讯

Your TTS shortlist is three shortlists, and they barely intersect

Every "best text-to-speech API" list I have read is ranked. Number one, number two, number three, with a verdict at the bottom. That shape cannot express the actual decision, and I want to show you why with something you can run. The problem is that the three things that decide a TTS vendor are measured in units that do not convert into each other. Price is dollars per million characters. Transport is a shape — held-open socket, chunked body, finished file. Compliance is a document that either exists or does not. There is no exchange rate between them, so there is no ordering. A ranked list has to pick one axis and pretend the others are tiebreakers. They are not tiebreakers. They are filters, and filters compose by intersection. The three sets Price spans about 40x. Google Cloud's legacy voices and Amazon Polly's standard engine sit at $4 per million characters. The mid-market — OpenAI's tts-1 , Deepgram Aura-1, Inworld TTS-2 Flash — clusters at $15. Cartesia runs $37.38 to $50. ElevenLabs is $166.11 at its Scale tier. A million characters is roughly 22 hours of speech, so at prototype volume this axis is noise; at a hundred million characters a year it is the difference between a $400 bill and a $16,600 one. Transport comes in three shapes and the difference is architectural, not incremental. WebSocket streaming holds a connection open and pushes audio as it is synthesised. The first syllable can reach the caller while the model is still working on the sentence. This is what a live agent needs. Chunked REST streams the response body back progressively. OpenAI works this way, and its docs recommend wav or pcm output specifically because those start playing sooner than a compressed container. Meaningfully better than waiting for a whole file; meaningfully worse than a held-open socket. Batch returns a finished file. Correct for narration, e-learning, anything rendered ahead of time. Wrong for conversation. Two entries in that column are routinely stated wrong, so th

2026-08-22 原文 →
AI 资讯

I Ran 300K Company API Lookups. 40K Hit Military Bases.

security, #api, #cybersecurity, #discuss On July 30, 2026, my batch job finished 300,000 domain-to-company lookups. 39,847 of them (13.3%) resolved to defense contractors, military-adjacent parent companies, or headquarters within a few miles of named bases. I wasn't hunting for that. I was just trying to clean a CRM. The same day, lina published a post about hijacking e164.arpa zones and accidentally logging hundreds of thousands of phone calls to military bases. Different protocol, same smell: an infrastructure lookup that was supposed to be boring turned into a classified-adjacent data spill. That parallel is what made me sit down and write this. Here is the exact call I used, with the live response for github.com so you can see the shape of the data before I explain what went wrong. import requests , json , time # Full source notes: https://github.com/On13uka/company-info-api RAPIDAPI_KEY = " YOUR_RAPIDAPI_KEY " BASE = " https://company-info1.p.rapidapi.com " def lookup ( domain ): r = requests . get ( f " { BASE } /lookup?domain= { domain } " , headers = { " X-RapidAPI-Key " : RAPIDAPI_KEY , " X-RapidAPI-Host " : " company-info1.p.rapidapi.com " }, timeout = 20 ) return r . json () print ( json . dumps ( lookup ( " github.com " ), indent = 2 )) The response I got back looked like this. It is a cached sample from a real call — the endpoint was asleep when I drafted this, but the fields are exactly what the pipeline consumed. { "domain" : "github.com" , "company_name" : "GitHub Inc" , "wikipedia" : "GitHub is a developer platform..." , "ceo" : "Thomas Dohmke" , "founded" : "2008" , "headquarters" : "San Francisco, California" , "employees" : "3000+" , "parent_company" : "Microsoft" , "twitter" : "@github" , "github_org" : { "repos" : 200 , "stars" : 50000 , "followers" : 12000 }, "health_score" : 78 } The Finding I started the job because a sales team had 300,000 stale domain records and wanted company names, headcounts, and a rough health score for each. The pla

2026-08-22 原文 →
AI 资讯

How to launch an AI automation agency offering voice AI agents for local businesses

You'll build a repeatable service that lets plumbers, dentists, and other service-business owners answer calls with a natural-sounding, AI-driven voice that schedules appointments, qualifies leads, and captures payments. The result is a hands-free phone front-desk that you can sell as a monthly subscription and use to acquire new clients for your agency. What you'll get: a working n8n workflow that wires Anthropic's Claude, ElevenLabs text-to-speech, and Twilio Programmable Voice together, plus a go-to client-acquisition script that turns the service into a scalable AI automation agency. What you need Tool Plan / Price* Role n8n (self-hosted Docker) Free (self-hosted) - see Docker Hub for latest image Orchestrates API calls, stores conversation state Twilio Programmable Voice Pay-as-you-go - check Twilio pricing page Provides inbound phone numbers and SIP bridge Anthropic Claude API Usage-based - check Anthropic pricing page Generates conversational replies ElevenLabs TTS API Usage-based - check ElevenLabs pricing page Turns Claude's text into a lifelike voice Cloudflare DNS + SSL Free tier available - verify limits Publishes a secure webhook for Twilio Git (optional) Free Version-controls workflow JSON *We avoid stating exact free-tier caps; always verify the current provider pricing. Estimated time-to-build: 12-16 hours total (including testing and client-onboarding script). Defining the core pieces Voice AI is the combination of speech-to-text, natural-language generation, and text-to-speech that lets a computer hold a phone conversation. In this guide we skip the speech-to-text step by letting Twilio forward the caller's audio to our n8n webhook; the rest happens via APIs. Key insight: The biggest revenue lever for an AI automation agency is the repeatable client-acquisition funnel, not the underlying technology. Building voice ai agents for local businesses Below is a step-by-step walkthrough. Every step mentions the exact UI field, API endpoint, or n8n node na

2026-08-22 原文 →
AI 资讯

how to build voice ai for inbound calls

You can have a Vapi agent answer every inbound call, ask qualifying questions, and hand the prospect off to Calendly to lock in a meeting - all without writing a single line of custom telephony code. The result is a self-contained voice AI agent that routes calls, captures lead data, and books calendar slots automatically. voice is the audible sound produced by a human speaker that can be captured, transmitted, and synthesized by software. voice AI agent is a software component that receives spoken input over a phone line, runs speech-to-text, applies a language model, and returns synthesized speech to the caller. Below you'll find everything you need to reproduce the exact workflow, from the required services to the n8n JSON that creates the Vapi agent, plus the pitfalls that usually bite new builders. What you need Tool Plan / Price Role Vapi Free tier or paid plan - check the Vapi pricing page Voice AI platform that hosts the conversational model and performs voice synthesis Twilio Pay-as-you-go voice minutes - check Twilio pricing Provides the inbound phone number and SIP termination for Vapi Calendly Free tier or paid plan - check Calendly pricing Calendar link generator and meeting scheduler n8n (self-hosted) Community edition - free (Docker) Orchestrates the webhook chain between Vapi, Twilio, and your CRM HubSpot CRM (optional) Free tier - check HubSpot pricing Stores qualified lead details for follow-up Estimated build time: 1-2 days for a minimal production-ready flow, assuming you already have accounts for the services above. how to build voice ai for inbound calls The core of the solution is a Vapi "agent" that runs a scripted dialogue, a Twilio phone number that forwards calls to Vapi, and an n8n workflow that receives the webhook payload, enriches the lead, and creates a Calendly event. Follow each numbered step precisely; the configuration values are written exactly as they appear in the UI. 1. Provision a Twilio phone number Log into the Twilio Conso

2026-08-22 原文 →
AI 资讯

The best free AI models 2026 for an automation-first business

The best free AI models 2026 are the ones that give you production-grade quality without a bill at the end of the month. In practice that means using Groq's ultra-low-latency mix, Google Gemini's 1 M-token free quota, Meta's LLaMA 2 (self-hosted), DeepSeek's open-source v2.5, and Mistral-7B-Base on a free cloud tier. Hook them up to an automation platform like n8n and you can run a full SaaS pipeline - lead scoring, email drafting, image captioning, or ticket routing - without paying for inference. Below you'll find the exact stack, a step-by-step build, the gotchas that usually bite newcomers, and a short FAQ so you can get the best free AI models 2026 live in under two hours. What you need Tool / Model Plan / Price (as of 2026) Role in the pipeline Groq (Mixtral-8x7B-instruct) Free tier: 200 k tokens / month, no credit-card required (see Groq pricing) Low-latency text generation for chat & summarisation Google Gemini 1.5 Flash Free tier: 1 M input tokens / month, 0.5 M output tokens / month (check Google Cloud AI) Multi-modal (text + image) support, best for classification and translation Meta LLaMA 2 13B Self-hosted Docker (CPU) - $0, or hosted on Runpod free credits (up to $5) Deep-knowledge base Q&A, fine-tuning on proprietary data DeepSeek-V2.5 Free tier on DeepSeek API: 150 k tokens / month (no card) Creative writing, code suggestions Mistral-7B-Base Free tier on Mistral Cloud: 100 k tokens / month (requires OAuth) Structured data extraction, function calling n8n (automation) Community Edition (self-hosted Docker) - free Orchestrates API calls, branching, retries Docker Desktop Free for personal use Container runtime for LLaMA 2 Node.js 18+ Free (runtime) Needed for custom JS functions inside n8n Estimated build time: 90 minutes for a fresh machine (install Docker, pull LLaMA, configure n8n) plus 30 minutes of testing. Total ~2 hours. Building a production-grade automation pipeline with the best free AI models 2026 Below is a concrete example: an inbound-lead

2026-08-22 原文 →
AI 资讯

The duration your video API accepts is not the duration it renders

A sequence I cut to a music bed was three frames out at the first transition, nine at the second, and by the sixth segment nothing lined up with anything. I had asked every generation for ten seconds. Every generation had returned a file that was not ten seconds. Nothing in the API said so. The request took duration: 10 , returned 200 , and produced an MP4 whose container duration was 8.708 . No warning field, no note in the response body, and — the part that actually cost me the afternoon — no mention of it on the docs page I had read three times. This is a general property of latent video models rather than a bug in one provider, and once you know the shape of it you can handle it in about twenty lines. Here is the shape. Seconds are the wrong unit A video diffusion model does not work on frames. It works on a compressed latent tensor, and the compression is temporal as well as spatial: a causal 3D autoencoder folds a run of input frames into a single latent frame. Because the encoder is causal, the first frame is kept whole and everything after it is compressed in groups. With a temporal stride of s , a clip of F frames becomes latent_frames = ( F - 1 ) / s + 1 which only divides evenly when F ≡ 1 (mod s) . Frame counts that miss that condition get padded or truncated, so implementations pick the nearest legal count and render that instead. Stack a second constraint on top — many of these models generate in fixed blocks of latent frames rather than one at a time — and the set of renderable lengths collapses into a short arithmetic progression: F = head + block · n n ∈ ℕ Every legal duration is one of those F values divided by the frame rate. Nothing between them is reachable. duration: 10 is not a request. It is a hint that gets snapped to a grid you were never shown. What the snapping does to users Three separate problems, and only the first is obvious. The output is not the length you promised. Your UI said 10s, the file is 8.708s, so your UI lied. Not by much,

2026-08-21 原文 →
AI 资讯

Why I Built a No-Signup QR & URL Utility Platform (And How to Use the API)

We've all been there: a client needs a quick QR code for a print campaign, or a short link for social media. You search Google, click the first result, and realize you need to create an account, verify your email, and potentially pay after 14 days. To solve this friction, we built klick.tools . It's a collection of simple web tools that just work - no signup, no expiration dates, and full GDPR compliance. What's inside? QR code generator: 7 content types (URL, text, WiFi, vCard, email, phone, geo), custom colors and module shapes, automatic WCAG contrast check, and clean export as PNG, SVG or PDF. Rendering happens in the browser, so the payload never leaves the device. URL shortener: shorten a link in seconds, see click stats, and change the target later without reprinting anything. The developer API We didn't want to build just another consumer site, so everything is backed by a REST API. Base URL: https://klick.tools/api/v1 . Responses are always JSON - lists as { data, count } , writes as { message, data } , errors as { error } with a stable machine-readable code . Creating a short link is a single POST, and it works without an account at all (rate-limited per IP): curl -X POST https://klick.tools/api/v1/links \ -H "Content-Type: application/json" \ -d '{"targetUrl": "https://example.com/a-very-long-campaign-url"}' With an API key ( kt_live_... , generated in your account) the link is bound to you, so you get click counts, editing and higher quotas. Pass it as a Bearer token or via x-api-key : const res = await fetch ( " https://klick.tools/api/v1/links " , { method : " POST " , headers : { " Content-Type " : " application/json " , Authorization : `Bearer ${ process . env . KLICK_TOOLS_API_KEY } ` , }, body : JSON . stringify ({ targetUrl : " https://example.com/landing " , title : " Summer campaign " , }), }); const { data } = await res . json (); console . log ( data . shortUrl , data . clickCount ); The same pattern covers QR codes via /api/v1/qr - create, li

2026-08-21 原文 →
AI 资讯

Iran Doesn't Need to Mine Hormuz — Your requirements.txt Is Already Rigged

Iran Doesn't Need to Mine Hormuz — Your requirements.txt Is Already Rigged Every headline you've read this week is a diversion. The Strait of Hormuz is not the target. You are. And you have been for months, possibly years, while you retweeted tanker tracking maps and debated whether Brent crude would touch $150. Iranian state-sponsored groups — OilRig, APT33, MuddyWater, Agrius — did not spend the last decade pivoting to cloud infrastructure so they could watch you panic about a waterway. They did it so they could own your build pipeline while you were distracted. And they have. This is not speculation. CISA Advisory AA24-038A explicitly maps Iranian APT campaigns against U.S. and allied critical infrastructure to cloud identity, Kubernetes targets, and software supply chains. Not SCADA. Not PLCs. Your kubectl binary. Your Helm charts. That FastAPI microservice running payment webhooks that you deployed on a Friday and haven't touched since March. The Revolutionary Guard does not need a mine. They need a maintainer who hasn't updated python-jose in fourteen months. The Theater and the Operation You watched the Strait. They watched your CI/CD. Geopolitical analysis is a spectator sport for infrastructure engineers, and Iranian cyber command is the bookie. While your LinkedIn feed filled with satellite imagery and retired admirals explained chokepoint logistics, the actual operation ran silently against: Public Helm charts with hardcoded cluster-admin ServiceAccounts FastAPI services with python-multipart handling unbounded file uploads on single-threaded Uvicorn workers .kube/config files exfiltrated from developer laptops in a dev-legacy namespace that predates your current CTO Terraform state stored in a single S3 bucket with versioning disabled and a policy written by someone who left in 2021 The Hormuz closure narrative is Information Operations . The closure of your API gateway due to an unpatched ASGI memory exhaustion vulnerability is the kinetic effect. You a

2026-08-21 原文 →
AI 资讯

5 states, 2 working filters: scraping US childcare license registries

Five states, one query language, and an "active licenses only" checkbox that only actually filters two of them. That's the trap in scraping US childcare-license open-data registries: Socrata SODA makes every state's API look identical, but "active" is defined — or not defined at all — differently in every dataset. Quick answer New York, Connecticut, Colorado, Delaware, and Texas all publish their childcare-facility registries through Socrata, and all five accept the same $where query syntax. But only NY and CT ship a server-side status filter this Actor can apply. Colorado and Delaware have no status column in the dataset at all — there's nothing to filter on. Texas does have a status column ( operation_status ), it's just not wired into the active-only filter, so toggling activeOnly doesn't touch Texas rows either way. Treating "active only" as a global switch that behaves the same everywhere will silently hand you closed and revoked facilities in three of the five states while you believe you filtered them out. STATE_CONFIGS : dict [ str , StateConfig ] = { " NY " : StateConfig (..., col_status = " facility_status " , active_where = " facility_status= ' Active '" ), " CT " : StateConfig (..., col_status = " status " , active_where = " status= ' ACTIVE '" ), " CO " : StateConfig (..., col_status = None ), # no status column to filter on " DE " : StateConfig (..., col_status = None ), # no status column to filter on " TX " : StateConfig (..., col_status = " operation_status " ), # status exists, filter isn't wired } Why does "active only" do nothing in three states? Because the filter is applied per-state, not globally, and only two states have both a status column and a configured $where fragment for it: async def _fetch_page (...): params = { " $limit " : str ( page_limit ), " $offset " : str ( offset ), " $order " : config . order_key } if active_only and config . active_where : params [ " $where " ] = config . active_where return await _get_with_retry ( session

2026-08-21 原文 →
AI 资讯

Same API standard, four incompatible schemas: scraping state cosmetology license registries

"Just query the Socrata API" is true and also useless advice. Socrata SODA is a real open standard — New York, Connecticut, Colorado, and Texas all expose their professional-license registries through the same $limit / $offset / $where query language. The standard ends there. What each state puts inside that standard is four unrelated data models wearing the same protocol. Quick answer Every state's cosmetology/barber/salon registry is one giant multi-profession table with its own column names, its own beauty-credential filter, and its own idea of what "active" means — and one state (Texas) doesn't expose a status column at all, so an activeOnly toggle is a silent no-op there. A generic Socrata client that assumes one schema will either miss most of the data or crash on the first state whose columns don't match. The fix is a per-state config object that maps each state's real column names to one canonical output row, with the active-license filter applied only where the underlying data supports it. @dataclass ( frozen = True ) class StateConfig : state : str endpoint : str order_key : str col_business_name : str | None col_licensee_name : str | None col_status : str | None base_where : str | None = None active_where : str | None = None Why does the same query return different professions per state? Cosmetology licenses don't get their own dataset — they're rows buried inside each state's entire professional-licensing table, next to electricians, dentists, and notaries. Filtering has to happen server-side, in SoQL, before pagination even starts, or you're downloading (and paying to store) irrelevant rows. Texas needs a starts_with() match across three license-type prefixes plus an Establishment wildcard; Connecticut needs an exact in() list of six credential names; Colorado needs a four-code in() list: TX_BEAUTY_WHERE = ( " starts_with(license_type, ' Cosmetology ' ) " " OR starts_with(license_type, ' Class A Barber ' ) " " OR starts_with(license_type, ' Barber ' ) "

2026-08-21 原文 →
AI 资讯

Google Trends API: the 200 OK that means you got soft-blocked

Google Trends has no public API. What it has is the same internal JSON endpoints the trends.google.com single-page app calls — and those endpoints do something most REST clients aren't built to survive: they answer with HTTP 200 and an empty body when Google decides you look like a bot. Quick answer A 200 OK from Google Trends' widgetdata endpoints does not mean you got data. If the response body is empty, Google soft-blocked the request without bothering to send a 429. The fix is to stop trusting the status code alone: check resp.text.strip() on every call that's supposed to return a payload, and if it's empty, rotate the proxy session and retry exactly like you would on a 429 — because that's what it functionally is. if status == 200 : if require_body and not resp . text . strip (): # Soft block: Google returns 200 with empty body when it detects bots. # Treat the same as 429 — rotate session and retry. logger . warning ( " %s: HTTP 200 but empty body (soft block, attempt %d/%d) " , ...) if proxy_cfg is not None : new_sid = _fresh_session_id () current_proxy_url = await proxy_cfg . new_url ( session_id = new_sid ) await asyncio . sleep ( delay ) continue return resp Why does a working response start with )]}' ? Every Trends JSON endpoint prepends an XSSI-protection prefix before the actual JSON body — a defence against cross-site script inclusion attacks that predates fetch() . Naive json.loads(resp.text) throws a JSONDecodeError on a perfectly healthy response. Worse, the prefix isn't even consistent: /trends/api/explore sends )]}'\n (no comma), some widgetdata endpoints send )]}',\n (with a comma). We check the longer variant first so a response using the short prefix doesn't get mis-stripped: XSSI_PREFIX = " )]} ' , \n " XSSI_PREFIX_NO_COMMA = " )]} ' \n " def _strip_xssi_prefix ( body : str ) -> str : if body . startswith ( XSSI_PREFIX ): return body [ len ( XSSI_PREFIX ):] if body . startswith ( XSSI_PREFIX_NO_COMMA ): return body [ len ( XSSI_PREFIX_NO_COMMA

2026-08-21 原文 →
AI 资讯

How to pull every open job from Greenhouse, Lever, Ashby and SmartRecruiters with public APIs (and monitor changes)

Job postings are one of the most underrated public data sources on the internet. Recruiters use them to spot placement opportunities, B2B teams read them as buying signals (a new Head of Data means data-tooling budget), and job seekers want to apply on day one — not when a posting finally reaches the aggregators. The usual instinct is to scrape career pages. Don't. Most tech companies host their careers page on one of a handful of Applicant Tracking Systems (ATS), and the four biggest ones — Greenhouse, Lever, Ashby and SmartRecruiters — all expose public, documented JSON APIs . No auth. No proxies. No brittle HTML selectors. The career page itself loads the same JSON you're about to fetch. In this tutorial we'll build a single-file Python tool that: fetches every open job for a company from any of the four ATS, auto-detects which ATS a company uses, normalizes everything into one clean schema, monitors changes — run it on a schedule and get only new / removed / changed postings. The four endpoints ATS Endpoint Greenhouse GET https://boards-api.greenhouse.io/v1/boards/{slug}/jobs?content=true Lever GET https://api.lever.co/v0/postings/{slug}?mode=json Ashby GET https://api.ashbyhq.com/posting-api/job-board/{slug} SmartRecruiters GET https://api.smartrecruiters.com/v1/companies/{slug}/postings (paginated) The {slug} is the company identifier you see in career-page URLs: boards.greenhouse.io/stripe → stripe , jobs.lever.co/spotify → spotify , jobs.ashbyhq.com/linear → linear , careers.smartrecruiters.com/Visa → Visa . Try one right now — no API key needed: curl -s "https://api.ashbyhq.com/posting-api/job-board/linear" | head -c 400 Step 1 — fetchers, one per ATS Each API returns a different shape, so we normalize as we fetch. Here are all four (Python 3, only requests ): import requests UA = { " User-Agent " : " ats-jobs-tutorial/1.0 " } def get_json ( url , params = None ): r = requests . get ( url , params = params , headers = UA , timeout = 30 ) r . raise_for_statu

2026-08-20 原文 →
AI 资讯

Driving DaVinci Resolve's Free Edition with Claude, From Inside the App

The wall Every MCP server that controls DaVinci Resolve connects to it the same way: a script running outside the app calls into Resolve's scripting API over the network. That works fine on Resolve Studio. On the free edition it doesn't work at all — Lite is sandboxed and blocks any script that isn't launched from inside Resolve itself. The one door left open Free Resolve still runs Python scripts launched from its own Workspace > Scripts menu. A menu script gets the resolve object injected for free, can run a long-lived loop, and — because the sandboxed app ships the com.apple.security.network.server entitlement — can open a localhost listening socket. That's the whole trick: the MCP server is the menu script. Claude Code ──HTTP JSON-RPC (MCP)──▶ 127.0.0.1:8765/mcp │ server runs INSIDE Resolve │ (Workspace > Scripts > Utility) ▼ command queue → main script thread ▼ global `resolve` object → Resolve API What it gets you 157 tools across editing, color, render, media pool, and Fusion title styling — driven from plain-language requests in Claude Code. Zero dependencies: pure Python standard library, so there's nothing to pip install into Resolve's bundled interpreter. Try it git clone https://github.com/2sem/davinci-resolve-lite-mcp.git cd davinci-resolve-lite-mcp ./install.sh macOS only for now. Full tools reference and demo video in the repo.

2026-08-20 原文 →
AI 资讯

Regex Against a PDF: The One Endpoint That Skips OCR Entirely

Most document pipelines have a reflex. A PDF comes in, and the first instinct is: run OCR, then parse it. That reflex costs time and money on documents that never needed it in the first place. Here's the distinction that gets skipped over. A PDF generated from Word, from an invoicing system, from a web page, from almost any modern software, is "born digital." Every character on the page is already stored as text, positioned and selectable, the same way this article's text is selectable in your browser. A scanned PDF is different: it's a photograph of a page, a grid of pixels with no text underneath it at all. OCR exists to solve that second problem. It reads the pixels and reconstructs a text layer that wasn't there. PDF OCR is PDF4me's endpoint for exactly that job, and its own documentation lists "Intelligent Processing: skip OCR when text is already searchable to optimize performance" as a named feature, which is the whole thesis of this article in one line. But if the PDF already has a text layer, running it through OCR first is a wasted step: extra processing time, extra cost, extra room for OCR to introduce recognition errors into text that was already perfect. A large share of the PDFs moving through business automation, generated invoices, exported reports, system-generated confirmations, contracts drafted in Word and exported to PDF, are born digital from the start. They don't need OCR. They need something that can read the text layer that's already there and pull out exactly the values that matter. That's what Extract Text by Expression does. One regex, one endpoint POST https://api.pdf4me.com/api/v2/ExtractTextByExpression No OCR step. No AI model. No template you have to build in a dashboard first. The request is small: Parameter Type Required Description docContent Base64 String Yes The source PDF, Base64-encoded docName String Yes Filename with .pdf extension expression String Yes A standard regular expression: groups, quantifiers, and anchors all supp

2026-08-20 原文 →
AI 资讯

Vibe Coding vs Prompt-Driven: One Year Later, the Debate Is Already Outdated

A year ago, the debate between “vibe coding” and “prompt-driven development” felt like the right lens for using AI in software. Today it’s outdated. The real frontier is no longer how to phrase a request, but how to build an environment that lets an AI agent explore, modify, and verify code safely. The shift from conversational prompts to structured development harnesses changes what it means to ship reliable software. Below are four concrete ways this evolution is reshaping daily work. From Prompt to Harness A finely crafted prompt can still produce a working feature, but it won’t prevent an agent from inventing APIs, skipping tests, or misreading business rules. The new bottleneck is the harness: Git for traceability, tests for feedback, linting for style, and explicit rules for constraints. When these elements are in place, even a short instruction like “fix the bug” can trigger a reliable, auditable workflow. Code is Abundant; Good Software is Rare Generating hundreds of lines of code costs almost nothing, but verifying that those lines align with product history, security policies, and hidden constraints is still manual. The developer’s scarcest resource is now judgment: deciding what to automate, what to document, and when to override the agent’s plausible but wrong solution. Documentation is Now for Machines README files and ADRs used to serve only humans. Today they also feed the agent’s context. A well-maintained AGENTS.md , coherent tests, and executable examples let an AI act with minimal prompting while remaining aligned with the team’s conventions. The repository becomes a self-explaining environment. Supervision is the Next Skill Single-agent workflows are giving way to multi-agent orchestration. Frontend, API, test analysis, and incident triage agents must coordinate without stepping on each other. Observability, conflict detection, and rollback mechanisms replace prompt tuning as the critical layer of control. The center of gravity has moved from “ho

2026-08-20 原文 →
AI 资讯

I Built a Claude Code Skill That Reverse-Engineers Undocumented APIs

I Built a Claude Code Skill That Reverse-Engineers Undocumented APIs Because "the docs are in the code" is not a documentation strategy. The Week I Lost to Grepping I joined a new team last month. Day 1 task: add a feature to the billing service. Day 1 reality: I opened the API docs and realized they were from 2022. Half the routes had been rewritten. The other half never had docs to begin with. So I did what every backend dev does. I grepped. grep -r "app.get|app.post|router." src/ --include="*.js" Four hours later, I had a notebook full of endpoints, a headache, and zero confidence that I had found everything. I found routes that worked but were not documented. I found docs for routes that did not exist anymore. I found one GET /invoices/:id endpoint with zero auth checks that had been sitting there since 2022. This is normal. And it should not be. The Idea What if I could drop a single file into a repo and have Claude Code map the entire API layer for me? Not from annotations. Not from existing OpenAPI specs. From the actual code. So I built it. Meet API Archaeologist API Archaeologist is a Claude Code / Codex CLI skill that reads your source code and reverse-engineers your API layer. It finds: • Internal endpoints — REST, GraphQL, gRPC, WebSockets • External integrations — third-party APIs, webhooks, SDK clients • Auth flows — JWT, OAuth, API keys, session cookies, RBAC • Security gaps — unauthenticated routes, hardcoded secrets, missing rate limits • Dead code — auth middleware with no endpoints, orphaned routes And it generates two things: API_DISCOVERY.md — A complete catalog with Mermaid diagrams openapi-draft.yaml — A draft OpenAPI spec How It Works The skill is just a SKILL.md file. Claude Code reads it and follows the instructions. It: Discovers route definitions Traces handlers, DTOs, middleware, services, and database calls Maps authentication and authorization Finds external API calls and integrations Flags potential security and reliability risks Gene

2026-08-19 原文 →
AI 资讯

GitHub API Rate Limits: an Unauthenticated 304 Still Costs You a Request

No token. One IP. July 29, 2026: GET /repos/python/cpython 200 5996 B remaining 32 -> 31 + If-None-Match (no Authorization header) 304 0 B remaining 31 -> 30 + If-None-Match 304 0 B remaining 30 -> 29 + If-None-Match 304 0 B remaining 29 -> 28 Three conditional requests. Three 304 Not Modified . Zero bytes of body across all three. Three requests gone from a bucket of 60 per hour. I opened the terminal to write the opposite post. The short version: if you call the GitHub REST API without an Authorization header, an If-None-Match request that comes back 304 still decrements x-ratelimit-remaining . The ETag saves you bytes. It does not save you quota. GitHub's documentation states the claim five times on one page and attaches the condition to two of them, and that clause falls off easily when a sentence gets quoted on its own. The post I meant to write My working title was something like "poll GitHub for free with ETags". I believed it. I had read the sentence about 304 responses not using your rate limit, I had repeated it to other people, and the plan was a tidy little piece with a before-and-after budget chart. The first run killed it. remaining went down. My first reaction was that my counter reading was wrong, which is the normal reaction and usually the correct one. It was not wrong. So the post changed, and the finding turned out to be worth more than the one I went in with. Does a 304 count against the GitHub rate limit? What the docs actually say Here is the part that matters, and I want to be precise because it would be easy and dishonest to turn this into "GitHub's docs are wrong". They are not. On the page Best practices for using the REST API the claim shows up five times. Two of the five carry a condition; three do not. Here is the strict one, the only place on the page where the condition is spelled out as a header: "Making a conditional request does not count against your primary rate limit if a 304 response is returned and the request was made while c

2026-08-19 原文 →
AI 资讯

Designing Reliable APIs for Production Applications: Lessons From Building Real-World Digital Products

Designing Reliable APIs for Production Applications: Lessons From Building Real-World Digital Products APIs are often described as the “bridge” between different parts of an application, but building a production-ready API involves much more than sending data from a frontend to a backend. Through my experience building full-stack applications, I've learned that a good API needs to be designed around reliability, security, maintainability and the actual needs of its users. Here are some of the principles I now consider when designing APIs: Design around resources, not screens An API shouldn't simply mirror the frontend interface. It should expose meaningful resources and operations that can evolve independently from the UI. Validate everything at the API boundary Data coming from a client should never be trusted automatically. Request validation, type checking and clear error responses help prevent invalid data from propagating through the system. Authentication is only the beginning An authenticated user should not automatically have access to every resource. APIs need appropriate authorisation and access-control rules for sensitive operations. Design predictable errors A useful API doesn't just return “something went wrong.” Clients need consistent status codes and structured error responses so that applications can respond appropriately. Think about idempotency This becomes particularly important when an API handles operations such as payments, orders or other actions that shouldn't accidentally happen twice because of a network retry. Don't expose unnecessary data APIs should return what the client needs rather than exposing entire database records. This reduces unnecessary data transfer and can also reduce the risk of accidentally exposing sensitive information. Logging and observability matter An API can appear perfect during development and still fail in production. Good logging and monitoring make it possible to understand what happened when requests fail, la

2026-08-19 原文 →