[{"data":1,"prerenderedAt":1378},["ShallowReactive",2],{"blog-\u002Fblog\u002Fship-a-linkedin-job-alert-bot":3,"blog-related-\u002Fblog\u002Fship-a-linkedin-job-alert-bot":1108},{"id":4,"title":5,"author":6,"body":7,"category":1093,"cover":1094,"description":1095,"draft":1096,"extension":1097,"image":1093,"launchCta":1093,"listingCover":1093,"meta":1098,"navigation":524,"ogImage":1093,"path":1099,"publishedAt":1100,"readTime":1093,"seo":1101,"stem":1102,"tags":1103,"toolCategory":1093,"updatedAt":1093,"__hash__":1107},"blogUnlisted\u002Fblog\u002Fship-a-linkedin-job-alert-bot.md","Ship a LinkedIn Job-Alert Bot With One Metered API Call","The Monid Team",{"type":8,"value":9,"toc":1078},"minimark",[10,17,21,74,84,89,130,134,139,148,156,164,168,225,233,240,244,247,271,297,301,307,359,385,389,395,460,471,475,478,653,668,674,678,681,936,939,972,983,987,990,1011,1017,1021,1030,1045,1054,1063,1067,1074],[11,12,13],"p",{},[14,15,16],"strong",{},"A working LinkedIn job-alert bot is one saved search, one metered scrape, and a five-line diff that surfaces only postings you have not seen before.",[11,18,20],{"style":19},"font-size:18px !important;line-height:1.65 !important;margin:0 0 24px;color:inherit;","Paste this to your coding agent and it will wire up the whole job-alert bot end to end, from the search query to the daily Slack ping.",[22,23,28],"pre",{"className":24,"code":25,"language":26,"meta":27,"style":27},"language-sh shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","set up https:\u002F\u002Fmonid.ai\u002FSKILL.md and use apify\u002Fharvestapi\u002Flinkedin-job-search to build a LinkedIn job-alert bot\n","sh","",[29,30,31],"code",{"__ignoreMap":27},[32,33,36,40,44,47,50,53,56,59,62,65,68,71],"span",{"class":34,"line":35},"line",1,[32,37,39],{"class":38},"s2Zo4","set",[32,41,43],{"class":42},"sfazB"," up",[32,45,46],{"class":42}," https:\u002F\u002Fmonid.ai\u002FSKILL.md",[32,48,49],{"class":42}," and",[32,51,52],{"class":42}," use",[32,54,55],{"class":42}," apify\u002Fharvestapi\u002Flinkedin-job-search",[32,57,58],{"class":42}," to",[32,60,61],{"class":42}," build",[32,63,64],{"class":42}," a",[32,66,67],{"class":42}," LinkedIn",[32,69,70],{"class":42}," job-alert",[32,72,73],{"class":42}," bot\n",[11,75,76,83],{},[77,78,82],"a",{"href":79,"rel":80},"https:\u002F\u002Fmonid.ai",[81],"nofollow","Monid"," is a pay-per-call data API marketplace: one integration and one wallet reach hundreds of external data endpoints, discovery and inspection are free, and you only pay when you actually run a job.",[85,86,88],"h2",{"id":87},"tldr","TL;DR",[90,91,92,104,113,120,127],"ul",{},[93,94,95,96,99,100,103],"li",{},"The paid step is a single call to ",[29,97,98],{},"apify"," endpoint ",[29,101,102],{},"\u002Fharvestapi\u002Flinkedin-job-search",", which returns full LinkedIn postings (title, description, company profile, applicant stats, direct apply URL) with no LinkedIn account or cookie and no cache.",[93,105,106,107,112],{},"Billing is per result: a fraction of a cent per job plus a tiny flat fee. Pass one focused query so cost stays predictable. Check the live number at ",[77,108,111],{"href":109,"rel":110},"https:\u002F\u002Fmonid.ai\u002Ftools",[81],"monid.ai\u002Ftools",".",[93,114,115,116,119],{},"The scraper runs once per query in ",[29,117,118],{},"jobTitles",", so a single query at a bounded limit is one predictable batch, not a runaway crawl.",[93,121,122,123,126],{},"The bot is five steps: inspect (free), run one bounded query, reduce with ",[29,124,125],{},"jq",", diff against a seen-ids file, then cron it to Slack or email.",[93,128,129],{},"Only new postings ever reach you, because every run compares fresh ids against the ones you already alerted.",[85,131,133],{"id":132},"set-up-monid-once","Set up Monid once",[135,136,138],"h3",{"id":137},"for-agents","For agents",[11,140,141,142,147],{},"Grab an API key at ",[77,143,146],{"href":144,"rel":145},"https:\u002F\u002Fapp.monid.ai\u002F",[81],"app.monid.ai",", then paste this to your agent and hand it the key:",[22,149,154],{"className":150,"code":152,"language":153},[151],"language-text","set up https:\u002F\u002Fmonid.ai\u002FSKILL.md\n","text",[29,155,152],{"__ignoreMap":27},[11,157,158,159,112],{},"It learns the whole discover, inspect, run workflow itself. More details in the ",[77,160,163],{"href":161,"rel":162},"https:\u002F\u002Fmonid.ai\u002Fdocs\u002Fguide\u002Fquickstart-skill",[81],"agent quickstart",[135,165,167],{"id":166},"for-humans","For humans",[22,169,173],{"className":170,"code":171,"language":172,"meta":27,"style":27},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","npm install -g @monid-ai\u002Fcli\nmonid keys add --label main --key \u003Cyour-api-key>\n","bash",[29,174,175,190],{"__ignoreMap":27},[32,176,177,181,184,187],{"class":34,"line":35},[32,178,180],{"class":179},"sBMFI","npm",[32,182,183],{"class":42}," install",[32,185,186],{"class":42}," -g",[32,188,189],{"class":42}," @monid-ai\u002Fcli\n",[32,191,193,196,199,202,205,208,211,215,218,222],{"class":34,"line":192},2,[32,194,195],{"class":179},"monid",[32,197,198],{"class":42}," keys",[32,200,201],{"class":42}," add",[32,203,204],{"class":42}," --label",[32,206,207],{"class":42}," main",[32,209,210],{"class":42}," --key",[32,212,214],{"class":213},"sMK4o"," \u003C",[32,216,217],{"class":42},"your-api-ke",[32,219,221],{"class":220},"sTEyZ","y",[32,223,224],{"class":213},">\n",[11,226,227,228,112],{},"More details in the ",[77,229,232],{"href":230,"rel":231},"https:\u002F\u002Fmonid.ai\u002Fdocs\u002Fguide\u002Fquickstart-cli",[81],"CLI quickstart",[11,234,235],{},[236,237],"img",{"alt":238,"src":239},"Pipeline from a saved search query through one metered scrape, jq reduction, and a seen-ids diff to a daily de-duplicated alert.","\u002Fimg\u002Fblog\u002Fship-a-linkedin-job-alert-bot-fig-1.png",[85,241,243],{"id":242},"step-1-inspect-the-endpoint-free","Step 1: Inspect the endpoint (free)",[11,245,246],{},"Before you spend anything, read the schema. Inspection is free, so you can confirm the input fields and the output shape without a single billed result.",[22,248,250],{"className":170,"code":249,"language":172,"meta":27,"style":27},"monid inspect -p apify -e \u002Fharvestapi\u002Flinkedin-job-search\n",[29,251,252],{"__ignoreMap":27},[32,253,254,256,259,262,265,268],{"class":34,"line":35},[32,255,195],{"class":179},[32,257,258],{"class":42}," inspect",[32,260,261],{"class":42}," -p",[32,263,264],{"class":42}," apify",[32,266,267],{"class":42}," -e",[32,269,270],{"class":42}," \u002Fharvestapi\u002Flinkedin-job-search\n",[11,272,273,274,276,277,280,281,284,285,288,289,292,293,296],{},"You will see the body fields you can send: ",[29,275,118],{}," (an array of search-query strings that accept boolean operators), ",[29,278,279],{},"locations"," (an array, use full names like \"United Kingdom\" rather than \"UK\"), plus optional filters for ",[29,282,283],{},"workplaceType"," (remote, hybrid, on-site), ",[29,286,287],{},"employmentType",", ",[29,290,291],{},"experienceLevel",", a salary range, a posting-date window, an ",[29,294,295],{},"easyApply"," flag, an applicant-count threshold, and a per-query result cap. On the output side each job carries the full title and description (text and HTML), the posting timestamp, compensation and benefits, workplace and employment attributes, company profile metadata (name, logo, employee count, industry), job stats (applicant and view counts), and the direct application URL.",[85,298,300],{"id":299},"step-2-run-one-bounded-query-the-only-paid-step","Step 2: Run one bounded query (the only paid step)",[11,302,303,304,306],{},"This is the single call that costs money. Send exactly one query in ",[29,305,118],{},", one or two locations, and a firm result cap so the batch size (and therefore the bill) is known before you press enter.",[22,308,310],{"className":170,"code":309,"language":172,"meta":27,"style":27},"monid run -p apify -e \u002Fharvestapi\u002Flinkedin-job-search \\\n  -i '{\"jobTitles\":[\"senior data engineer\"],\"locations\":[\"United States\"],\"workplaceType\":[\"remote\"],\"limit\":50}' \\\n  -w -o jobs.json\n",[29,311,312,331,347],{"__ignoreMap":27},[32,313,314,316,319,321,323,325,328],{"class":34,"line":35},[32,315,195],{"class":179},[32,317,318],{"class":42}," run",[32,320,261],{"class":42},[32,322,264],{"class":42},[32,324,267],{"class":42},[32,326,327],{"class":42}," \u002Fharvestapi\u002Flinkedin-job-search",[32,329,330],{"class":220}," \\\n",[32,332,333,336,339,342,345],{"class":34,"line":192},[32,334,335],{"class":42},"  -i",[32,337,338],{"class":213}," '",[32,340,341],{"class":42},"{\"jobTitles\":[\"senior data engineer\"],\"locations\":[\"United States\"],\"workplaceType\":[\"remote\"],\"limit\":50}",[32,343,344],{"class":213},"'",[32,346,330],{"class":220},[32,348,350,353,356],{"class":34,"line":349},3,[32,351,352],{"class":42},"  -w",[32,354,355],{"class":42}," -o",[32,357,358],{"class":42}," jobs.json\n",[11,360,361,362,365,366,369,370,373,374,377,378,381,382,384],{},"The ",[29,363,364],{},"-i"," flag passes the JSON body, ",[29,367,368],{},"-w"," waits for the async scrape to finish, and ",[29,371,372],{},"-o jobs.json"," writes the raw results to disk. Keep the JSON minimal: ",[29,375,376],{},"limit"," is the per-query result cap, so ",[29,379,380],{},"50"," means at most fifty jobs for this one query. Because the scraper runs once per query in ",[29,383,118],{},", one query keeps the cost to a single predictable batch.",[85,386,388],{"id":387},"step-3-reduce-each-job-to-the-fields-you-care-about","Step 3: Reduce each job to the fields you care about",[11,390,391,392,394],{},"The raw payload is rich, but an alert only needs a handful of fields. Use ",[29,393,125],{}," to collapse each job down to a compact record.",[22,396,398],{"className":170,"code":397,"language":172,"meta":27,"style":27},"jq '[.[] | {\n  id: .id,\n  title: .title,\n  company: .companyName,\n  location: .location,\n  url: .applyUrl,\n  postedAt: .postedAt\n}]' jobs.json > matches.json\n",[29,399,400,409,414,419,425,431,437,443],{"__ignoreMap":27},[32,401,402,404,406],{"class":34,"line":35},[32,403,125],{"class":179},[32,405,338],{"class":213},[32,407,408],{"class":42},"[.[] | {\n",[32,410,411],{"class":34,"line":192},[32,412,413],{"class":42},"  id: .id,\n",[32,415,416],{"class":34,"line":349},[32,417,418],{"class":42},"  title: .title,\n",[32,420,422],{"class":34,"line":421},4,[32,423,424],{"class":42},"  company: .companyName,\n",[32,426,428],{"class":34,"line":427},5,[32,429,430],{"class":42},"  location: .location,\n",[32,432,434],{"class":34,"line":433},6,[32,435,436],{"class":42},"  url: .applyUrl,\n",[32,438,440],{"class":34,"line":439},7,[32,441,442],{"class":42},"  postedAt: .postedAt\n",[32,444,446,449,451,454,457],{"class":34,"line":445},8,[32,447,448],{"class":42},"}]",[32,450,344],{"class":213},[32,452,453],{"class":42}," jobs.json",[32,455,456],{"class":213}," >",[32,458,459],{"class":42}," matches.json\n",[11,461,462,463,466,467,470],{},"Now ",[29,464,465],{},"matches.json"," is a tidy array of ",[29,468,469],{},"{id, title, company, location, url, postedAt}"," objects, ready to compare and ready to render into a message.",[85,472,474],{"id":473},"step-4-diff-against-a-seen-ids-file-so-you-only-surface-new-postings","Step 4: Diff against a seen-ids file so you only surface new postings",[11,476,477],{},"An alert bot that re-sends the same fifty jobs every morning is noise. Keep a running list of ids you have already alerted, and each run emit only the ids that are new.",[22,479,481],{"className":170,"code":480,"language":172,"meta":27,"style":27},"# ids returned this run\njq -r '.[].id' matches.json | sort -u > today-ids.txt\n\n# ids you have never alerted before\ncomm -13 seen-ids.txt today-ids.txt > new-ids.txt\n\n# the full records for just the new ids\njq --slurpfile ids \u003C(jq -R -s 'split(\"\\n\") | map(select(length>0))' new-ids.txt) \\\n   '[.[] | select(.id as $i | $ids[0] | index($i))]' matches.json > new-jobs.json\n\n# remember what you alerted, so tomorrow it stays quiet\ncat seen-ids.txt today-ids.txt | sort -u > seen-ids.tmp && mv seen-ids.tmp seen-ids.txt\n",[29,482,483,489,520,526,531,550,554,559,592,610,615,621],{"__ignoreMap":27},[32,484,485],{"class":34,"line":35},[32,486,488],{"class":487},"sHwdD","# ids returned this run\n",[32,490,491,493,496,498,501,503,506,509,512,515,517],{"class":34,"line":192},[32,492,125],{"class":179},[32,494,495],{"class":42}," -r",[32,497,338],{"class":213},[32,499,500],{"class":42},".[].id",[32,502,344],{"class":213},[32,504,505],{"class":42}," matches.json",[32,507,508],{"class":213}," |",[32,510,511],{"class":179}," sort",[32,513,514],{"class":42}," -u",[32,516,456],{"class":213},[32,518,519],{"class":42}," today-ids.txt\n",[32,521,522],{"class":34,"line":349},[32,523,525],{"emptyLinePlaceholder":524},true,"\n",[32,527,528],{"class":34,"line":421},[32,529,530],{"class":487},"# ids you have never alerted before\n",[32,532,533,536,539,542,545,547],{"class":34,"line":427},[32,534,535],{"class":179},"comm",[32,537,538],{"class":42}," -13",[32,540,541],{"class":42}," seen-ids.txt",[32,543,544],{"class":42}," today-ids.txt",[32,546,456],{"class":213},[32,548,549],{"class":42}," new-ids.txt\n",[32,551,552],{"class":34,"line":433},[32,553,525],{"emptyLinePlaceholder":524},[32,555,556],{"class":34,"line":439},[32,557,558],{"class":487},"# the full records for just the new ids\n",[32,560,561,563,566,569,572,574,577,579,582,584,587,590],{"class":34,"line":445},[32,562,125],{"class":179},[32,564,565],{"class":42}," --slurpfile",[32,567,568],{"class":42}," ids",[32,570,571],{"class":213}," \u003C(",[32,573,125],{"class":179},[32,575,576],{"class":42}," -R -s ",[32,578,344],{"class":213},[32,580,581],{"class":42},"split(\"\\n\") | map(select(length>0))",[32,583,344],{"class":213},[32,585,586],{"class":42}," new-ids.txt",[32,588,589],{"class":213},")",[32,591,330],{"class":220},[32,593,595,598,601,603,605,607],{"class":34,"line":594},9,[32,596,597],{"class":213},"   '",[32,599,600],{"class":42},"[.[] | select(.id as $i | $ids[0] | index($i))]",[32,602,344],{"class":213},[32,604,505],{"class":42},[32,606,456],{"class":213},[32,608,609],{"class":42}," new-jobs.json\n",[32,611,613],{"class":34,"line":612},10,[32,614,525],{"emptyLinePlaceholder":524},[32,616,618],{"class":34,"line":617},11,[32,619,620],{"class":487},"# remember what you alerted, so tomorrow it stays quiet\n",[32,622,624,627,629,631,633,635,637,639,642,645,648,650],{"class":34,"line":623},12,[32,625,626],{"class":179},"cat",[32,628,541],{"class":42},[32,630,544],{"class":42},[32,632,508],{"class":213},[32,634,511],{"class":179},[32,636,514],{"class":42},[32,638,456],{"class":213},[32,640,641],{"class":42}," seen-ids.tmp",[32,643,644],{"class":213}," &&",[32,646,647],{"class":179}," mv",[32,649,641],{"class":42},[32,651,652],{"class":42}," seen-ids.txt\n",[11,654,655,656,659,660,663,664,667],{},"On the first run ",[29,657,658],{},"seen-ids.txt"," is empty (create it with ",[29,661,662],{},"touch seen-ids.txt","), so everything is new. On every run after that, ",[29,665,666],{},"new-jobs.json"," holds only postings you have never seen.",[11,669,670],{},[236,671],{"alt":672,"src":673},"The seen-ids diff: today's job ids compared against seen-ids.txt, dropping already-alerted ids and surfacing only new-today postings, which are then appended back.","\u002Fimg\u002Fblog\u002Fship-a-linkedin-job-alert-bot-fig-2.png",[85,675,677],{"id":676},"step-5-wire-it-into-a-daily-cron-that-posts-to-slack","Step 5: Wire it into a daily cron that posts to Slack",[11,679,680],{},"Wrap the four steps in a script and schedule it. A single daily run is a single metered call, and only the new matches leave the machine.",[22,682,684],{"className":170,"code":683,"language":172,"meta":27,"style":27},"#!\u002Fusr\u002Fbin\u002Fenv bash\nset -euo pipefail\ncd \"$HOME\u002Flinkedin-alert-bot\"\n\nmonid run -p apify -e \u002Fharvestapi\u002Flinkedin-job-search \\\n  -i '{\"jobTitles\":[\"senior data engineer\"],\"locations\":[\"United States\"],\"workplaceType\":[\"remote\"],\"limit\":50}' \\\n  -w -o jobs.json\n\n# ... Step 3 and Step 4 reduction and diff here ...\n\nif [ -s new-ids.txt ]; then\n  jq -r '.[] | \"*\\(.title)* at \\(.company) (\\(.location))\\n\\(.url)\"' new-jobs.json \\\n    | while read -r line; do\n        curl -s -X POST -H 'Content-type: application\u002Fjson' \\\n          --data \"{\\\"text\\\": $(jq -Rs . \u003C\u003C\u003C \"$line\")}\" \\\n          \"$SLACK_WEBHOOK_URL\" > \u002Fdev\u002Fnull\n      done\nfi\n",[29,685,686,691,701,718,722,738,750,758,762,767,771,792,811,834,860,908,924,930],{"__ignoreMap":27},[32,687,688],{"class":34,"line":35},[32,689,690],{"class":487},"#!\u002Fusr\u002Fbin\u002Fenv bash\n",[32,692,693,695,698],{"class":34,"line":192},[32,694,39],{"class":38},[32,696,697],{"class":42}," -euo",[32,699,700],{"class":42}," pipefail\n",[32,702,703,706,709,712,715],{"class":34,"line":349},[32,704,705],{"class":38},"cd",[32,707,708],{"class":213}," \"",[32,710,711],{"class":220},"$HOME",[32,713,714],{"class":42},"\u002Flinkedin-alert-bot",[32,716,717],{"class":213},"\"\n",[32,719,720],{"class":34,"line":421},[32,721,525],{"emptyLinePlaceholder":524},[32,723,724,726,728,730,732,734,736],{"class":34,"line":427},[32,725,195],{"class":179},[32,727,318],{"class":42},[32,729,261],{"class":42},[32,731,264],{"class":42},[32,733,267],{"class":42},[32,735,327],{"class":42},[32,737,330],{"class":220},[32,739,740,742,744,746,748],{"class":34,"line":433},[32,741,335],{"class":42},[32,743,338],{"class":213},[32,745,341],{"class":42},[32,747,344],{"class":213},[32,749,330],{"class":220},[32,751,752,754,756],{"class":34,"line":439},[32,753,352],{"class":42},[32,755,355],{"class":42},[32,757,358],{"class":42},[32,759,760],{"class":34,"line":445},[32,761,525],{"emptyLinePlaceholder":524},[32,763,764],{"class":34,"line":594},[32,765,766],{"class":487},"# ... Step 3 and Step 4 reduction and diff here ...\n",[32,768,769],{"class":34,"line":612},[32,770,525],{"emptyLinePlaceholder":524},[32,772,773,777,780,783,786,789],{"class":34,"line":617},[32,774,776],{"class":775},"s7zQu","if",[32,778,779],{"class":213}," [",[32,781,782],{"class":213}," -s",[32,784,785],{"class":220}," new-ids.txt ",[32,787,788],{"class":213},"];",[32,790,791],{"class":775}," then\n",[32,793,794,797,799,801,804,806,809],{"class":34,"line":623},[32,795,796],{"class":179},"  jq",[32,798,495],{"class":42},[32,800,338],{"class":213},[32,802,803],{"class":42},".[] | \"*\\(.title)* at \\(.company) (\\(.location))\\n\\(.url)\"",[32,805,344],{"class":213},[32,807,808],{"class":42}," new-jobs.json",[32,810,330],{"class":220},[32,812,814,817,820,823,825,828,831],{"class":34,"line":813},13,[32,815,816],{"class":213},"    |",[32,818,819],{"class":775}," while",[32,821,822],{"class":38}," read",[32,824,495],{"class":42},[32,826,827],{"class":42}," line",[32,829,830],{"class":213},";",[32,832,833],{"class":775}," do\n",[32,835,837,840,842,845,848,851,853,856,858],{"class":34,"line":836},14,[32,838,839],{"class":179},"        curl",[32,841,782],{"class":42},[32,843,844],{"class":42}," -X",[32,846,847],{"class":42}," POST",[32,849,850],{"class":42}," -H",[32,852,338],{"class":213},[32,854,855],{"class":42},"Content-type: application\u002Fjson",[32,857,344],{"class":213},[32,859,330],{"class":220},[32,861,863,866,868,871,874,876,878,881,884,886,889,892,894,897,900,903,906],{"class":34,"line":862},15,[32,864,865],{"class":42},"          --data",[32,867,708],{"class":213},[32,869,870],{"class":42},"{",[32,872,873],{"class":220},"\\\"",[32,875,153],{"class":42},[32,877,873],{"class":220},[32,879,880],{"class":42},": ",[32,882,883],{"class":213},"$(",[32,885,125],{"class":179},[32,887,888],{"class":42}," -Rs . ",[32,890,891],{"class":213},"\u003C\u003C\u003C",[32,893,708],{"class":213},[32,895,896],{"class":220},"$line",[32,898,899],{"class":213},"\")",[32,901,902],{"class":42},"}",[32,904,905],{"class":213},"\"",[32,907,330],{"class":220},[32,909,911,914,917,919,921],{"class":34,"line":910},16,[32,912,913],{"class":213},"          \"",[32,915,916],{"class":220},"$SLACK_WEBHOOK_URL",[32,918,905],{"class":213},[32,920,456],{"class":213},[32,922,923],{"class":42}," \u002Fdev\u002Fnull\n",[32,925,927],{"class":34,"line":926},17,[32,928,929],{"class":775},"      done\n",[32,931,933],{"class":34,"line":932},18,[32,934,935],{"class":775},"fi\n",[11,937,938],{},"Add it to crontab for a 9am daily run:",[22,940,942],{"className":170,"code":941,"language":172,"meta":27,"style":27},"0 9 * * * \u002Fhome\u002Fyou\u002Flinkedin-alert-bot\u002Frun.sh >> \u002Fhome\u002Fyou\u002Flinkedin-alert-bot\u002Flog.txt 2>&1\n",[29,943,944],{"__ignoreMap":27},[32,945,946,949,953,956,958,960,963,966,969],{"class":34,"line":35},[32,947,948],{"class":179},"0",[32,950,952],{"class":951},"sbssI"," 9",[32,954,955],{"class":220}," *",[32,957,955],{"class":220},[32,959,955],{"class":220},[32,961,962],{"class":42}," \u002Fhome\u002Fyou\u002Flinkedin-alert-bot\u002Frun.sh",[32,964,965],{"class":213}," >>",[32,967,968],{"class":42}," \u002Fhome\u002Fyou\u002Flinkedin-alert-bot\u002Flog.txt",[32,970,971],{"class":213}," 2>&1\n",[11,973,974,975,978,979,982],{},"Swap the ",[29,976,977],{},"curl"," block for a ",[29,980,981],{},"sendmail"," or email API call if you prefer inbox alerts over Slack.",[85,984,986],{"id":985},"cost-tally","Cost tally",[11,988,989],{},"Add up the whole bot and only one line has a price on it.",[90,991,992,995,1001],{},[93,993,994],{},"Inspect (Step 1): free.",[93,996,997,998,1000],{},"Run (Step 2): one call, billed per result. At a ",[29,999,376],{}," of 50 that is at most fifty results, each a fraction of a cent, plus a tiny flat fee. A daily 9am cron is roughly thirty of these calls a month.",[93,1002,1003,1004,288,1006,1008,1009,112],{},"Reduce, diff, and alert (Steps 3 to 5): free, all local ",[29,1005,125],{},[29,1007,535],{},", and ",[29,1010,977],{},[11,1012,1013,1014,112],{},"So the running cost of the bot is one small metered scrape per day, and you pay for results, not for uptime or a monthly seat. The live per-result number is on ",[77,1015,111],{"href":109,"rel":1016},[81],[85,1018,1020],{"id":1019},"faq","FAQ",[11,1022,1023,1026,1027,1029],{},[14,1024,1025],{},"Do I need a LinkedIn account or cookie to run this?","\nNo. The ",[29,1028,102],{}," endpoint returns fresh, uncached postings without any LinkedIn login, session, or cookie. You send a query and get structured jobs back.",[11,1031,1032,1035,1036,1038,1039,1041,1042,112],{},[14,1033,1034],{},"How do I keep the cost predictable?","\nSend a single query in ",[29,1037,118],{}," and set a firm result cap. The scraper runs once per query, so total results are roughly the number of queries times the per-query limit. One query at ",[29,1040,376],{}," 50 is one bounded batch, and you can watch the exact per-result figure at ",[77,1043,111],{"href":109,"rel":1044},[81],[11,1046,1047,1050,1051,1053],{},[14,1048,1049],{},"Why diff against a seen-ids file instead of just re-sending everything?","\nBecause a good alert is only the delta. The scrape returns the current matching set every run, so without the ",[29,1052,658],{}," comparison you would re-alert the same jobs daily. The diff in Step 4 guarantees each posting reaches you exactly once.",[11,1055,1056,1059,1060,1062],{},[14,1057,1058],{},"Can I widen the search to several titles or locations later?","\nYes, but remember the billing math: each extra query in ",[29,1061,118],{}," is another metered run, and each extra location can multiply results. Start with one query, confirm the cost and quality, then add scope deliberately.",[85,1064,1066],{"id":1065},"try-it","Try it",[11,1068,1069,1070,112],{},"You can stand up this bot in an afternoon: inspect for free, run one bounded query, and let the diff keep your alerts clean. Every morning you get only the LinkedIn postings you have not seen, for the price of a few results a day. Start at ",[77,1071,1073],{"href":79,"rel":1072},[81],"monid.ai",[1075,1076,1077],"style",{},"html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":27,"searchDepth":192,"depth":192,"links":1079},[1080,1081,1085,1086,1087,1088,1089,1090,1091,1092],{"id":87,"depth":192,"text":88},{"id":132,"depth":192,"text":133,"children":1082},[1083,1084],{"id":137,"depth":349,"text":138},{"id":166,"depth":349,"text":167},{"id":242,"depth":192,"text":243},{"id":299,"depth":192,"text":300},{"id":387,"depth":192,"text":388},{"id":473,"depth":192,"text":474},{"id":676,"depth":192,"text":677},{"id":985,"depth":192,"text":986},{"id":1019,"depth":192,"text":1020},{"id":1065,"depth":192,"text":1066},null,"\u002Fimg\u002Fblog\u002Fship-a-linkedin-job-alert-bot.png","Build a LinkedIn job-alert bot that scrapes fresh postings, de-dupes by id, and pings Slack daily. One metered call, a fraction of a cent per result. No cookie.",false,"md",{},"\u002Fblog\u002Fship-a-linkedin-job-alert-bot","2026-07-31",{"title":5,"description":1095},"blog\u002Fship-a-linkedin-job-alert-bot",[98,1104,1105,1106],"harvestapi","linkedin","job-scraping","jGaAqsmLCdiVWquuw6U9TWnKpDhnmYlhXhUllFtwIus",[1109,1171,1239,1305],{"id":1110,"title":1111,"author":1093,"body":1112,"category":1093,"cover":1156,"description":27,"draft":1096,"extension":1097,"image":1093,"launchCta":1157,"listingCover":1093,"meta":1160,"navigation":524,"ogImage":1093,"path":1161,"publishedAt":1162,"readTime":1093,"seo":1163,"stem":1164,"tags":1165,"toolCategory":1093,"updatedAt":1093,"__hash__":1170},"blog\u002Fblog\u002Fakta-pro-is-now-available-on-monid.md","Introducing private markets\ndata for agents",{"type":8,"value":1113,"toc":1152},[1114,1118,1126,1129,1133,1139,1146,1149],[85,1115,1117],{"id":1116},"what-is-aktapro","What is akta.pro",[11,1119,1120,1125],{},[77,1121,1124],{"href":1122,"rel":1123},"https:\u002F\u002Fwww.akta.pro\u002F",[81],"akta.pro"," is a private company data and signals API for\nAI agents. Company Database covers 20M+ companies with 75+ structured fields\neach. News Signals delivers deduplicated, entity-resolved company news,\nindustry news, and signals on open-ended topics, all scored for impact and\nsentiment.",[11,1127,1128],{},"Private-company research is usually scattered across databases, news feeds,\nreview sites, and web search. akta.pro turns that into structured API calls, so\nan agent gets the right company context and keeps moving.",[85,1130,1132],{"id":1131},"what-is-monid","What is Monid",[11,1134,1135,1138],{},[77,1136,82],{"href":79,"rel":1137},[81]," is the tool layer for agents. It lets agents connect\nto all the tools and APIs they need, without managing signups, API keys, or\nsubscriptions.",[11,1140,1141,1142,112],{},"Today, Monid provides tools for social media scraping, web search, image and\nmusic generation, people data search, weather APIs, ",[77,1143,1145],{"href":109,"rel":1144},[81],"and more",[1147,1148],"hr",{},[11,1150,1151],{},"On Monid, akta.pro becomes available as part of that same layer. Your agent can\nrequest private-company context, call akta.pro through Monid, receive structured\nmarket data, and continue the task. Private markets research should feel like\nany other tool call: describe the company or sector, get the signal, keep\nbuilding.",{"title":27,"searchDepth":192,"depth":192,"links":1153},[1154,1155],{"id":1116,"depth":192,"text":1117},{"id":1131,"depth":192,"text":1132},"\u002Fimg\u002Fblog\u002Fakta-pro-is-now-available-on-monid-v2.png",{"label":1158,"command":1159},"Give your agent this line to get started.","set up https:\u002F\u002Fmonid.ai\u002FSKILL.md and use akta.pro to research recent news, company enrichment, and alternative signals for Databricks",{},"\u002Fblog\u002Fakta-pro-is-now-available-on-monid","2026-07-07",{"title":1111,"description":27},"blog\u002Fakta-pro-is-now-available-on-monid",[1166,1167,1168,1169],"agents","partner-tools","private-markets","data","05ST9oH9qSQ4_vNxcczvHDEyev2JDIqBwMiM-zelWJo",{"id":1172,"title":1173,"author":1093,"body":1174,"category":1093,"cover":1228,"description":1229,"draft":1096,"extension":1097,"image":1093,"launchCta":1093,"listingCover":1093,"meta":1230,"navigation":524,"ogImage":1093,"path":1231,"publishedAt":1232,"readTime":1093,"seo":1233,"stem":1234,"tags":1235,"toolCategory":1093,"updatedAt":1093,"__hash__":1238},"blog\u002Fblog\u002Fyour-claude-code-can-now-make-phone-calls.md","Your Claude Code can now make phone calls",{"type":8,"value":1175,"toc":1224},[1176,1179,1188,1192,1200,1203,1205,1210,1216,1218,1221],[11,1177,1178],{"style":19},"Copy this line to your agent to make your first phone call.",[22,1180,1182],{"className":24,"code":1181,"language":26,"meta":27,"style":27},"set up https:\u002F\u002Fmonid.ai\u002FSKILL.md and use Saperly to call my phone number to confirm the connection works\n",[29,1183,1184],{"__ignoreMap":27},[32,1185,1186],{"class":34,"line":35},[32,1187,1181],{},[85,1189,1191],{"id":1190},"what-is-saperly","What is Saperly",[11,1193,1194,1199],{},[77,1195,1198],{"href":1196,"rel":1197},"https:\u002F\u002Fsaperly.com\u002F",[81],"Saperly"," is phone infrastructure for AI agents. It gives\nan agent a real phone number with voice, SMS, routing, spend controls, and\ncompliance built in, without making the builder manage carrier accounts or\ntelephony paperwork.",[11,1201,1202],{},"Your agent can confirm an appointment, follow up on a lead, check availability,\nor route a conversation without leaving the workflow it is already running.",[85,1204,1132],{"id":1131},[11,1206,1207,1138],{},[77,1208,82],{"href":79,"rel":1209},[81],[11,1211,1212,1213,112],{},"Today, Monid provides tools for social media scraping, web search, image \u002F\nmusic \u002F 3d model generation, people data search, weather APIs, ",[77,1214,1145],{"href":109,"rel":1215},[81],[1147,1217],{},[11,1219,1220],{},"On Monid, Saperly becomes available as part of that same layer. Your agent can\nrequest a phone call, use Saperly through Monid, receive the result, and keep\ngoing. Calling should feel like any other tool call: describe the outcome, let\nthe agent handle the phone work, and continue the task.",[1075,1222,1223],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":27,"searchDepth":192,"depth":192,"links":1225},[1226,1227],{"id":1190,"depth":192,"text":1191},{"id":1131,"depth":192,"text":1132},"\u002Fimg\u002Fblog\u002Fyour-claude-code-can-now-make-phone-calls.png","Saperly is now available on Monid. Your agent can now make phone calls for you.",{},"\u002Fblog\u002Fyour-claude-code-can-now-make-phone-calls","2026-07-05",{"title":1173,"description":1229},"blog\u002Fyour-claude-code-can-now-make-phone-calls",[1166,1167,1236,1237],"voice","phone","Wp96EVH5j2eyHDSu2f5Rtv0RYmyWX7frAhalel9fOus",{"id":1240,"title":1241,"author":1093,"body":1242,"category":1093,"cover":1294,"description":1295,"draft":1096,"extension":1097,"image":1093,"launchCta":1093,"listingCover":1093,"meta":1296,"navigation":524,"ogImage":1093,"path":1297,"publishedAt":1298,"readTime":1093,"seo":1299,"stem":1300,"tags":1301,"toolCategory":1093,"updatedAt":1093,"__hash__":1304},"blog\u002Fblog\u002Fintroducing-suzanne-chatgpt-for-3d-models.md","Introducing\nClaude for 3D models",{"type":8,"value":1243,"toc":1290},[1244,1247,1256,1260,1268,1271,1273,1278,1283,1285,1288],[11,1245,1246],{"style":19},"Copy this line to your agent to generate your 3D model.",[22,1248,1250],{"className":24,"code":1249,"language":26,"meta":27,"style":27},"set up https:\u002F\u002Fmonid.ai\u002FSKILL.md and create a 3D model for a rabbit\n",[29,1251,1252],{"__ignoreMap":27},[32,1253,1254],{"class":34,"line":35},[32,1255,1249],{},[85,1257,1259],{"id":1258},"what-is-suzanne","What is Suzanne",[11,1261,1262,1267],{},[77,1263,1266],{"href":1264,"rel":1265},"https:\u002F\u002Fwww.suzanne3d.com",[81],"Suzanne"," is an AI-native 3D modeling tool that turns a prompt into a\nusable 3D asset. Instead of opening a modeling tool, blocking out forms,\nadding details, and exporting by hand, you describe what you want and let\nSuzanne generate the model for you.",[11,1269,1270],{},"That changes who can create 3D objects. Product teams can prototype visual\nideas faster. Game builders can rough out props and characters without\nwaiting on a full art pass. Agents can generate assets as part of a larger\nworkflow, then hand those files to downstream tools for rendering, testing,\nor iteration.",[85,1272,1132],{"id":1131},[11,1274,1275,1138],{},[77,1276,82],{"href":79,"rel":1277},[81],[11,1279,1141,1280,112],{},[77,1281,1145],{"href":109,"rel":1282},[81],[1147,1284],{},[11,1286,1287],{},"On Monid, Suzanne becomes available as part of that same layer. Your agent can\nask for the 3D asset it needs, call Suzanne through Monid, and continue the task.\n3D creation should feel as direct as text generation: describe the thing, get\nthe artifact, keep building.",[1075,1289,1223],{},{"title":27,"searchDepth":192,"depth":192,"links":1291},[1292,1293],{"id":1258,"depth":192,"text":1259},{"id":1131,"depth":192,"text":1132},"\u002Fimg\u002Fblog\u002Fintroducing-suzanne-chatgpt-for-3d-models.png","Suzanne is now available on Monid. Turn any idea into a production-ready 3D model in one prompt.",{},"\u002Fblog\u002Fintroducing-suzanne-chatgpt-for-3d-models","2026-06-25",{"title":1241,"description":1295},"blog\u002Fintroducing-suzanne-chatgpt-for-3d-models",[1302,1166,1303],"3d","creative-tools","Mz475YlhLBgR80gyiTlL2MhfALZKYwbl4Rfwy96HZG0",{"id":1306,"title":1307,"author":1093,"body":1308,"category":1093,"cover":1367,"description":1368,"draft":1096,"extension":1097,"image":1093,"launchCta":1093,"listingCover":1093,"meta":1369,"navigation":524,"ogImage":1093,"path":1370,"publishedAt":1371,"readTime":1093,"seo":1372,"stem":1373,"tags":1374,"toolCategory":1093,"updatedAt":1093,"__hash__":1377},"blog\u002Fblog\u002Fminimax-is-now-available-on-monid.md","MiniMax is now available on Monid",{"type":8,"value":1309,"toc":1362},[1310,1313,1322,1326,1334,1338,1341,1343,1349,1355,1357,1360],[11,1311,1312],{"style":19},"Copy this line to your agent to create music.",[22,1314,1316],{"className":24,"code":1315,"language":26,"meta":27,"style":27},"set up https:\u002F\u002Fmonid.ai\u002FSKILL.md and create a song with MiniMax Music 2.6\n",[29,1317,1318],{"__ignoreMap":27},[32,1319,1320],{"class":34,"line":35},[32,1321,1315],{},[85,1323,1325],{"id":1324},"minimax-music-26","MiniMax Music 2.6",[11,1327,1328,1333],{},[77,1329,1332],{"href":1330,"rel":1331},"https:\u002F\u002Fwww.minimax.io",[81],"MiniMax"," Music 2.6 turns a prompt into music your agent can use right away. Describe the style, mood, lyrics, or use case, and generate a track inside the same workflow.",[85,1335,1337],{"id":1336},"minimax-text-to-image-image-01","MiniMax Text-to-Image image-01",[11,1339,1340],{},"MiniMax image-01 turns text prompts into images. Ask for a concept, scene, product visual, or creative asset, and let your agent generate it through Monid.",[85,1342,1132],{"id":1131},[11,1344,1345,1348],{},[77,1346,82],{"href":79,"rel":1347},[81]," is the tool layer for agents. It lets agents connect to all the tools and APIs they need, without managing signups, API keys, or subscriptions.",[11,1350,1351,1352,112],{},"Today, Monid provides tools for social media scraping, web search, image and music generation, people data search, weather APIs, ",[77,1353,1145],{"href":109,"rel":1354},[81],[1147,1356],{},[11,1358,1359],{},"On Monid, MiniMax becomes part of the same tool layer your agent already uses. Describe what you need, generate the image or music, and keep building.",[1075,1361,1223],{},{"title":27,"searchDepth":192,"depth":192,"links":1363},[1364,1365,1366],{"id":1324,"depth":192,"text":1325},{"id":1336,"depth":192,"text":1337},{"id":1131,"depth":192,"text":1132},"\u002Fimg\u002Fblog\u002Fminimax-is-now-available-on-monid.png","Create images and music with MiniMax models through Monid.",{},"\u002Fblog\u002Fminimax-is-now-available-on-monid","2026-06-24",{"title":1307,"description":1368},"blog\u002Fminimax-is-now-available-on-monid",[1166,1303,1375,1376],"image-generation","music-generation","B3dZqIjNJNK7Y9ysAenI0XzKobOZMlEP87FRWrW19Vc",1786670266441]