diff --git a/snippets/whitelabel/ai/batches/id.mdx b/snippets/whitelabel/ai/batches/id.mdx new file mode 100644 index 0000000..6acde92 --- /dev/null +++ b/snippets/whitelabel/ai/batches/id.mdx @@ -0,0 +1,5 @@ +```shell +curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ +'https://render.joinmassive.com/ai/batches'\ +'?id=b3829f53-abc9-4e62-8a65-2d9359d586d6' +``` diff --git a/snippets/whitelabel/ai/batches/prompts.mdx b/snippets/whitelabel/ai/batches/prompts.mdx new file mode 100644 index 0000000..6456a20 --- /dev/null +++ b/snippets/whitelabel/ai/batches/prompts.mdx @@ -0,0 +1,15 @@ +```shell +curl -X POST 'https://render.joinmassive.com/ai/batches' \ +-H "Authorization: Bearer $MASSIVE_TOKEN" \ +-H 'Content-Type: application/json' \ +-d '{ + "prompts": [ + "Where can I buy a vintage guitar?", + "Help me find guitar repair shops nearby.", + "Do any local stores sell vinyl records?", + "[Additional prompts here]" + ], + "country": "US", + "subdivision": "TN" +}' +``` diff --git a/snippets/whitelabel/ai/completions.mdx b/snippets/whitelabel/ai/completions.mdx new file mode 100644 index 0000000..6acde92 --- /dev/null +++ b/snippets/whitelabel/ai/completions.mdx @@ -0,0 +1,5 @@ +```shell +curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ +'https://render.joinmassive.com/ai/batches'\ +'?id=b3829f53-abc9-4e62-8a65-2d9359d586d6' +``` diff --git a/snippets/whitelabel/ai/device.mdx b/snippets/whitelabel/ai/device.mdx index fb96883..773c47c 100644 --- a/snippets/whitelabel/ai/device.mdx +++ b/snippets/whitelabel/ai/device.mdx @@ -1,6 +1,6 @@ ```shell curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ 'https://render.joinmassive.com/ai'\ -'?prompt=what+happened+to+blackberry'\ -'&device=blackberry+playbook' +'?prompt=What+happened+to+blackberry%3F'\ +'&device=Blackberry+PlayBook' ``` diff --git a/snippets/whitelabel/ai/expiration.mdx b/snippets/whitelabel/ai/expiration.mdx index 8037a6d..1a081f1 100644 --- a/snippets/whitelabel/ai/expiration.mdx +++ b/snippets/whitelabel/ai/expiration.mdx @@ -1,8 +1,6 @@ -### Cachebusting - ```shell curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ 'https://render.joinmassive.com/ai'\ -'?prompt=current+weather'\ +'?prompt=Show+the+current+weather.'\ '&expiration=0' ``` diff --git a/snippets/whitelabel/ai/id.mdx b/snippets/whitelabel/ai/id.mdx index 513678c..fa0c42e 100644 --- a/snippets/whitelabel/ai/id.mdx +++ b/snippets/whitelabel/ai/id.mdx @@ -1,5 +1,5 @@ ```shell curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ -'https://render.joinmassive.com/ai/completions'\ +'https://render.joinmassive.com/ai'\ '?id=1851dab8-4619-409f-893f-47dd3a180bc3' ``` diff --git a/snippets/whitelabel/ai/mode.mdx b/snippets/whitelabel/ai/mode.mdx index bb9bb9f..d264950 100644 --- a/snippets/whitelabel/ai/mode.mdx +++ b/snippets/whitelabel/ai/mode.mdx @@ -1,6 +1,6 @@ ```shell curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ 'https://render.joinmassive.com/ai'\ -'?prompt=prolonged+fasting'\ +'?prompt=Summarize+the+latest+research+on+prolonged+fasting.'\ '&mode=async' ``` diff --git a/snippets/whitelabel/ai/subdivision.mdx b/snippets/whitelabel/ai/subdivision.mdx index bbb582a..b85a5a3 100644 --- a/snippets/whitelabel/ai/subdivision.mdx +++ b/snippets/whitelabel/ai/subdivision.mdx @@ -1,7 +1,7 @@ ```shell curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ 'https://render.joinmassive.com/ai'\ -'?prompt=find+vintage+guitar+stores'\ -'&country=us'\ -'&subdivision=tn' +'?prompt=Where+can+I+buy+a+vintage+guitar%3F'\ +'&country=US'\ +'&subdivision=TN' ``` diff --git a/snippets/whitelabel/browser/batches/id.mdx b/snippets/whitelabel/browser/batches/id.mdx new file mode 100644 index 0000000..0ad8a20 --- /dev/null +++ b/snippets/whitelabel/browser/batches/id.mdx @@ -0,0 +1,5 @@ +```shell +curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ +'https://render.joinmassive.com/browser/batches'\ +'?id=cfde9b46-f599-49ab-844e-9b2461285284' +``` diff --git a/snippets/whitelabel/browser/batches/urls.mdx b/snippets/whitelabel/browser/batches/urls.mdx new file mode 100644 index 0000000..af735d6 --- /dev/null +++ b/snippets/whitelabel/browser/batches/urls.mdx @@ -0,0 +1,15 @@ +```shell +curl -X POST 'https://render.joinmassive.com/browser/batches' \ +-H "Authorization: Bearer $MASSIVE_TOKEN" \ +-H 'Content-Type: application/json' \ +-d '{ + "urls": [ + "https://guitars.com/", + "https://cartervintage.com/", + "https://musiccityvintageguitars.com/", + "[Additional URLs here]" + ], + "country": "US", + "city": "Nashville" +}' +``` diff --git a/snippets/whitelabel/browser/cdp/cdp2rest.mdx b/snippets/whitelabel/browser/cdp/cdp2rest.mdx new file mode 100644 index 0000000..88e9a79 --- /dev/null +++ b/snippets/whitelabel/browser/cdp/cdp2rest.mdx @@ -0,0 +1,107 @@ +```js +#!/usr/bin/env node +import puppeteer from 'puppeteer'; + +const cdpEndpoint = 'wss://render.joinmassive.com/browser'; +const restEndpoint = 'https://render.joinmassive.com/browser'; +const apiToken = process.env.MASSIVE_TOKEN; +const sessionId = Date.now(); +const headers = { + Authorization: `Bearer ${apiToken}`, + Cookie: `session=${sessionId}` +}; +const orderUrl = 'https://httpbin.org/forms/post'; +const receiptUrl = 'https://httpbin.org/post'; +const sizeSelector = '[name="size"][value="medium"]'; +const toppingSelector = '[name="topping"][value="onion"]'; +const buttonSelector = 'button'; +const timeoutMs = 180_000; +const delayMs = 1_000; + +console.log(`Connecting via CDP with session ${sessionId} ...`); + +const browser = await puppeteer.connect({ + browserWSEndpoint: cdpEndpoint, + headers +}); +const [page] = await browser.pages(); +let response = await page.goto(orderUrl); + +if (response?.ok()) { + console.log(`"${await page.title()}" interacted with successfully`); +} else { + console.error( + 'Page interaction failure:', + await page.evaluate(() => { + return document.body.innerText; + }) + ); + + process.exit(1); +} + +await page.waitForSelector(sizeSelector); +await page.click(sizeSelector); +await new Promise((resolve) => { + setTimeout(resolve, delayMs); +}); +await page.waitForSelector(toppingSelector); +await page.click(toppingSelector); +await new Promise((resolve) => { + setTimeout(resolve, delayMs); +}); +await page.waitForSelector(buttonSelector); +await Promise.all([ + page.waitForNavigation({ waitUntil: 'domcontentloaded' }), + page.click(buttonSelector) +]); +await browser.disconnect(); + +console.log(`Making REST request with session ${sessionId} ...`); + +const controller = new AbortController(); +const timeoutId = setTimeout(() => { + controller.abort(); +}, timeoutMs); + +try { + response = await fetch( + `${restEndpoint}?url=${encodeURIComponent(receiptUrl)}&expiration=0`, + { headers, signal: controller.signal } + ); +} catch (error) { + const hasTimedOut = error.name == 'AbortError'; + response = new Response( + hasTimedOut ? 'Request timed out' : 'Unknown error occurred', + { status: hasTimedOut ? 504 : 500 } + ); +} finally { + clearTimeout(timeoutId); +} + +if (response.ok) { + const data = await response.json(); + + if ( + data.form && + typeof data.form.size == 'string' && + typeof data.form.topping == 'string' + ) { + console.log( + 'Ordered ' + + data.form.size.toLowerCase() + + ' pizza with ' + + data.form.topping.toLowerCase() + + ' successfully' + ); + } else { + console.error('Receipt was malformed'); + + process.exit(1); + } +} else { + console.error('Order form read failure:', (await response.text()).trimEnd()); + + process.exit(1); +} +``` diff --git a/snippets/whitelabel/browser/cdp/close.mdx b/snippets/whitelabel/browser/cdp/close.mdx new file mode 100644 index 0000000..2a4d900 --- /dev/null +++ b/snippets/whitelabel/browser/cdp/close.mdx @@ -0,0 +1,3 @@ +```py +browser.close() +``` diff --git a/snippets/whitelabel/browser/cdp/device.mdx b/snippets/whitelabel/browser/cdp/device.mdx new file mode 100644 index 0000000..68f50ca --- /dev/null +++ b/snippets/whitelabel/browser/cdp/device.mdx @@ -0,0 +1,10 @@ +```js +const browser = await puppeteer.connect({ + browserWSEndpoint: + 'wss://render.joinmassive.com/browser' + + '?device=Blackberry+Playbook', + headers: { + Authorization: `Bearer ${process.env.MASSIVE_TOKEN}` + } +}); +``` diff --git a/snippets/whitelabel/browser/cdp/difficulty.mdx b/snippets/whitelabel/browser/cdp/difficulty.mdx new file mode 100644 index 0000000..700c748 --- /dev/null +++ b/snippets/whitelabel/browser/cdp/difficulty.mdx @@ -0,0 +1,10 @@ +```js +const browser = await puppeteer.connect({ + browserWSEndpoint: + 'wss://render.joinmassive.com/browser' + + '?difficulty=medium', + headers: { + Authorization: `Bearer ${process.env.MASSIVE_TOKEN}` + } +}); +``` diff --git a/snippets/whitelabel/browser/cdp/disconnect.mdx b/snippets/whitelabel/browser/cdp/disconnect.mdx new file mode 100644 index 0000000..a9eb10d --- /dev/null +++ b/snippets/whitelabel/browser/cdp/disconnect.mdx @@ -0,0 +1,3 @@ +```js +await browser.disconnect(); +``` diff --git a/snippets/whitelabel/browser/cdp/e2e.mdx b/snippets/whitelabel/browser/cdp/e2e.mdx new file mode 100644 index 0000000..c7f9f75 --- /dev/null +++ b/snippets/whitelabel/browser/cdp/e2e.mdx @@ -0,0 +1,26 @@ +```py +#!/usr/bin/env python3 +import os +from playwright.sync_api import sync_playwright + +ENDPOINT = 'wss://render.joinmassive.com/browser' +API_TOKEN = os.environ['MASSIVE_TOKEN'] +URL = 'https://example.com/' + +print(f"Connecting to {ENDPOINT} ...") + +with sync_playwright() as playwright: + browser = playwright.chromium.connect_over_cdp( + ENDPOINT, + headers={'Authorization': f"Bearer {API_TOKEN}"} + ) + context = browser.contexts[0] + page = context.pages[0] + + print(f"Going to {URL} ...") + + page.goto(URL) + print(f"URL: {page.url}") + print(f"Title: {page.title()}") + browser.close() +``` diff --git a/snippets/whitelabel/browser/cdp/goto.mdx b/snippets/whitelabel/browser/cdp/goto.mdx new file mode 100644 index 0000000..cd51a4a --- /dev/null +++ b/snippets/whitelabel/browser/cdp/goto.mdx @@ -0,0 +1,7 @@ +```js +const [page] = await browser.pages(); + +await page.goto('https://example.com/'); +console.log('URL:', page.url()); +console.log('Title:', await page.title()); +``` diff --git a/snippets/whitelabel/browser/cdp/playwright.mdx b/snippets/whitelabel/browser/cdp/playwright.mdx new file mode 100644 index 0000000..9f1430e --- /dev/null +++ b/snippets/whitelabel/browser/cdp/playwright.mdx @@ -0,0 +1,14 @@ +```py +#!/usr/bin/env python3 +import os +from playwright.sync_api import sync_playwright + +with sync_playwright() as playwright: + browser = playwright.chromium.connect_over_cdp( + 'wss://render.joinmassive.com/browser', + headers={ + 'Authorization': + f"Bearer {os.environ['MASSIVE_TOKEN']}" + } + ) +``` diff --git a/snippets/whitelabel/browser/cdp/puppeteer.mdx b/snippets/whitelabel/browser/cdp/puppeteer.mdx new file mode 100644 index 0000000..ad21f80 --- /dev/null +++ b/snippets/whitelabel/browser/cdp/puppeteer.mdx @@ -0,0 +1,11 @@ +```js +#!/usr/bin/env node +import puppeteer from 'puppeteer'; + +const browser = await puppeteer.connect({ + browserWSEndpoint: 'wss://render.joinmassive.com/browser', + headers: { + Authorization: `Bearer ${process.env.MASSIVE_TOKEN}` + } +}); +``` diff --git a/snippets/whitelabel/browser/cdp/rest2cdp.mdx b/snippets/whitelabel/browser/cdp/rest2cdp.mdx new file mode 100644 index 0000000..7324512 --- /dev/null +++ b/snippets/whitelabel/browser/cdp/rest2cdp.mdx @@ -0,0 +1,149 @@ +```js +#!/usr/bin/env node +import puppeteer from 'puppeteer'; + +const restEndpoint = 'https://render.joinmassive.com/browser'; +const cdpEndpoint = 'wss://render.joinmassive.com/browser'; +const apiToken = process.env.MASSIVE_TOKEN; +const headers = { Authorization: `Bearer ${apiToken}` }; +const sessionId = Date.now(); +const orderUrl = 'https://httpbin.org/forms/post'; +const sizeSelector = '[name="size"][value="small"]'; +const toppingSelector = '[name="topping"][value="cheese"]'; +const buttonSelector = 'button'; +const requestTimeoutMs = 180_000; +const connectionTimeoutMs = 10_000; +const delayMs = 1_000; +const delay = (ms) => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); +}; +const getCookies = (response) => { + const cookies = response.headers.getSetCookie?.() ?? []; + const keyvals = cookies.map((cookie) => { + return cookie.split(';', 1)[0]; + }); + + return keyvals.join('; '); +}; + +console.log( + 'Making REST request with session', + sessionId, + '...' +); + +const controller = new AbortController(); +let timeoutId = setTimeout(() => { + controller.abort(); +}, requestTimeoutMs); +let response; + +try { + const url = + restEndpoint + + '?url=' + + encodeURIComponent(orderUrl) + + '&session=' + + sessionId + + '&expiration=0'; + response = await fetch( + url, + { headers, signal: controller.signal } + ); +} catch (error) { + const hasTimedOut = error.name == 'AbortError'; + response = new Response( + hasTimedOut + ? 'Request timed out' + : 'Unknown error occurred', + { status: hasTimedOut ? 504 : 500 } + ); +} finally { + clearTimeout(timeoutId); +} + +if (response.ok) { + console.log('Order form read successfully'); +} else { + const text = await response.text(); + + console.error('Order form read failure:', text.trimEnd()); + + process.exit(1); +} + +console.log( + 'Connecting via CDP with session', + sessionId, + '...' +); + +timeoutId = setTimeout(() => { + console.error('Connection timed out'); + + process.exit(1); +}, connectionTimeoutMs); +const url = `${cdpEndpoint}?session=${sessionId}`; +const browser = await puppeteer.connect({ + browserWSEndpoint: url, + headers: { ...headers, Cookie: getCookies(response) } +}); + +clearTimeout(timeoutId); + +const page = (await browser.pages()).find((page) => { + return page.url().includes(orderUrl); +}); + +if (page) { + console.log('Session handed off successfully'); +} else { + console.error('Session handoff failure'); + + process.exit(1); +} + +await page.waitForSelector(sizeSelector); +await page.click(sizeSelector); +await delay(delayMs); +await page.waitForSelector(toppingSelector); +await page.click(toppingSelector); +await delay(delayMs); +await page.waitForSelector(buttonSelector); +await Promise.all([ + page.waitForNavigation({ waitUntil: 'domcontentloaded' }), + page.click(buttonSelector) +]); + +try { + const json = await page.evaluate(() => { + return document.body.innerText; + }); + const data = JSON.parse(json); + + if ( + data.form && + typeof data.form.size == 'string' && + typeof data.form.topping == 'string' + ) { + console.log( + 'Ordered', + data.form.size.toLowerCase(), + 'pizza with', + data.form.topping.toLowerCase() + ); + } else { + console.error('Receipt was malformed'); + + process.exit(1); + } +} catch (error) { + console.error('Receipt parse failure:', error.message); + + process.exit(1); +} + +await browser.disconnect(); +``` diff --git a/snippets/whitelabel/browser/city.mdx b/snippets/whitelabel/browser/city.mdx index 7dc5326..ef8b6bc 100644 --- a/snippets/whitelabel/browser/city.mdx +++ b/snippets/whitelabel/browser/city.mdx @@ -2,6 +2,6 @@ curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ 'https://render.joinmassive.com/browser'\ '?url=https://guitars.com/'\ -'&country=us'\ +'&country=US'\ '&city=Nashville' ``` diff --git a/snippets/whitelabel/browser/content.mdx b/snippets/whitelabel/browser/content.mdx new file mode 100644 index 0000000..0ad8a20 --- /dev/null +++ b/snippets/whitelabel/browser/content.mdx @@ -0,0 +1,5 @@ +```shell +curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ +'https://render.joinmassive.com/browser/batches'\ +'?id=cfde9b46-f599-49ab-844e-9b2461285284' +``` diff --git a/snippets/whitelabel/browser/device.mdx b/snippets/whitelabel/browser/device.mdx index f6a1bf9..a0a7500 100644 --- a/snippets/whitelabel/browser/device.mdx +++ b/snippets/whitelabel/browser/device.mdx @@ -2,5 +2,5 @@ curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ 'https://render.joinmassive.com/browser'\ '?url=https://crackberry.com/'\ -'&device=blackberry+playbook' +'&device=Blackberry+Playbook' ``` diff --git a/snippets/whitelabel/browser/expiration.mdx b/snippets/whitelabel/browser/expiration.mdx index 0f2854a..abfb802 100644 --- a/snippets/whitelabel/browser/expiration.mdx +++ b/snippets/whitelabel/browser/expiration.mdx @@ -1,5 +1,3 @@ -### Cachebusting - ```shell curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ 'https://render.joinmassive.com/browser'\ diff --git a/snippets/whitelabel/browser/id.mdx b/snippets/whitelabel/browser/id.mdx index 3e22ad0..941467a 100644 --- a/snippets/whitelabel/browser/id.mdx +++ b/snippets/whitelabel/browser/id.mdx @@ -1,5 +1,5 @@ ```shell curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ -'https://render.joinmassive.com/browser/content'\ +'https://render.joinmassive.com/browser'\ '?id=21cb972e-0e0f-47bb-9ce9-65b99e9cee77' ``` diff --git a/snippets/whitelabel/browser/session.mdx b/snippets/whitelabel/browser/session.mdx deleted file mode 100644 index d100ed1..0000000 --- a/snippets/whitelabel/browser/session.mdx +++ /dev/null @@ -1,6 +0,0 @@ -```shell -curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ --H 'Cookie: session=12345' \ -'https://render.joinmassive.com/browser'\ -'?url=https://www.amazon.com/s?k=luggage' -``` diff --git a/snippets/whitelabel/search/awaiting.mdx b/snippets/whitelabel/search/awaiting.mdx index fe3fd84..71625cb 100644 --- a/snippets/whitelabel/search/awaiting.mdx +++ b/snippets/whitelabel/search/awaiting.mdx @@ -1,9 +1,7 @@ -### Lazy results - ```shell curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ 'https://render.joinmassive.com/search'\ -'?terms=how+tall+is+mount+everest'\ +'?terms=how+tall+is+mount+everest%3F'\ '&awaiting=ai'\ '&awaiting=answers' ``` diff --git a/snippets/whitelabel/search/batches/id.mdx b/snippets/whitelabel/search/batches/id.mdx new file mode 100644 index 0000000..242d046 --- /dev/null +++ b/snippets/whitelabel/search/batches/id.mdx @@ -0,0 +1,5 @@ +```shell +curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ +'https://render.joinmassive.com/search/batches'\ +'?id=a0482596-c2ad-445a-a435-727002156a20' +``` diff --git a/snippets/whitelabel/search/batches/terms.mdx b/snippets/whitelabel/search/batches/terms.mdx new file mode 100644 index 0000000..e240454 --- /dev/null +++ b/snippets/whitelabel/search/batches/terms.mdx @@ -0,0 +1,9 @@ +```shell +curl -X POST 'https://render.joinmassive.com/search/batches' \ +-H "Authorization: Bearer $MASSIVE_TOKEN" \ +-H 'Content-Type: application/json' \ +-d '{ + "terms": ["musical instruments"], + "country": "US" +}' +``` diff --git a/snippets/whitelabel/search/callback.mdx b/snippets/whitelabel/search/callback.mdx index 1f494cf..9d87cb8 100644 --- a/snippets/whitelabel/search/callback.mdx +++ b/snippets/whitelabel/search/callback.mdx @@ -1,5 +1,3 @@ -### Push notification - ```shell curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ 'https://render.joinmassive.com/search'\ diff --git a/snippets/whitelabel/search/country.mdx b/snippets/whitelabel/search/country.mdx index bf57367..257ff2f 100644 --- a/snippets/whitelabel/search/country.mdx +++ b/snippets/whitelabel/search/country.mdx @@ -2,5 +2,5 @@ curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ 'https://render.joinmassive.com/search'\ '?terms=musical+instruments'\ -'&country=us' +'&country=US' ``` diff --git a/snippets/whitelabel/search/device.mdx b/snippets/whitelabel/search/device.mdx new file mode 100644 index 0000000..e826424 --- /dev/null +++ b/snippets/whitelabel/search/device.mdx @@ -0,0 +1,6 @@ +```shell +curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ +'https://render.joinmassive.com/search'\ +'?terms=blackberry'\ +'&device=Blackberry+PlayBook' +``` diff --git a/snippets/whitelabel/search/devices.mdx b/snippets/whitelabel/search/devices.mdx new file mode 100644 index 0000000..a3940c9 --- /dev/null +++ b/snippets/whitelabel/search/devices.mdx @@ -0,0 +1,4 @@ +```shell +curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ +'https://render.joinmassive.com/search/devices' +``` diff --git a/snippets/whitelabel/search/id.mdx b/snippets/whitelabel/search/id.mdx index 04b4b73..3045706 100644 --- a/snippets/whitelabel/search/id.mdx +++ b/snippets/whitelabel/search/id.mdx @@ -1,5 +1,5 @@ ```shell curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ -'https://render.joinmassive.com/search/results'\ +'https://render.joinmassive.com/search'\ '?id=078fd246-f0f7-44a0-aabb-cadd7b12454f' ``` diff --git a/snippets/whitelabel/search/offset.mdx b/snippets/whitelabel/search/offset.mdx index 56bb4d4..4d5c30c 100644 --- a/snippets/whitelabel/search/offset.mdx +++ b/snippets/whitelabel/search/offset.mdx @@ -1,5 +1,3 @@ -### Results omission - ```shell curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ 'https://render.joinmassive.com/search'\ diff --git a/snippets/whitelabel/search/results.mdx b/snippets/whitelabel/search/results.mdx new file mode 100644 index 0000000..242d046 --- /dev/null +++ b/snippets/whitelabel/search/results.mdx @@ -0,0 +1,5 @@ +```shell +curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ +'https://render.joinmassive.com/search/batches'\ +'?id=a0482596-c2ad-445a-a435-727002156a20' +``` diff --git a/snippets/whitelabel/search/subaccount.mdx b/snippets/whitelabel/search/subaccount.mdx index ad2b3b5..8c1970e 100644 --- a/snippets/whitelabel/search/subaccount.mdx +++ b/snippets/whitelabel/search/subaccount.mdx @@ -1,5 +1,3 @@ -### Accounting - ```shell curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ 'https://render.joinmassive.com/search'\ diff --git a/snippets/whitelabel/search/url.mdx b/snippets/whitelabel/search/url.mdx index 5b23e48..e7a27de 100644 --- a/snippets/whitelabel/search/url.mdx +++ b/snippets/whitelabel/search/url.mdx @@ -1,5 +1,3 @@ -### Alternative URL - ```shell curl -H "Authorization: Bearer $MASSIVE_TOKEN" \ 'https://render.joinmassive.com/search'\ diff --git a/web-render/ai.mdx b/web-render/ai.mdx index 940d96b..edd7146 100644 --- a/web-render/ai.mdx +++ b/web-render/ai.mdx @@ -49,8 +49,9 @@ The keys and values **{companyName}** supports are as follows: | `device` | ⬜ | The name as returned by the [devices resource](#device-emulation) of the device to emulate chatting on (these names are case insensitive but must include form- or URL-encoded spaces and punctuation marks); device emulation is unused by default | | `language` (planned) | ⬜ | The commonly spelled name or [two-letter ISO code](https://www.loc.gov/standards/iso639-2/php/code_list.php) of the language to chat in (these names and codes are case insensitive but required to include form- or URL-encoded spaces and punctuation marks); the language is unset by default | | `display` (planned) | ⬜ | The commonly spelled name or [two-letter ISO code](https://www.loc.gov/standards/iso639-2/php/code_list.php) of the chat interface's display language (these names and codes are case insensitive but required to include form- or URL-encoded spaces and punctuation marks); the display language is unset by default or set to the language if given | -| `format` | ⬜ | The format to output to, `json`, `rendered`, or `raw` (see the [section below](#response-format)); `json` is the default format | +| `format` | ⬜ | The format to output to, `json`, `rendered`, or `raw` (planned) (see the [section below](#response-format)); `json` is the default format | | `expiration` | ⬜ | The age in days of when to consider a cached completion expired, where `0` disables caching; `1` is the default number of days before expiration | +| `callback` | ⬜ | The encoded HTTP or HTTPS callback URL or Amazon SQS queue URL or ARN of up to 2,047 characters to notify when the (prerequisite) asynchronous completion has been retrieved; any SQS queue must grant `sqs:SendMessage` permission to the `arn:aws:iam::180363035301:role/api-instance` AWS principal | ### Device emulation @@ -77,7 +78,7 @@ Then, pass your device name of choice into your chat request: ### Response format -Completions are returned as structured JSON, rendered HTML, or raw (unrendered) HTML. +Completions are returned as structured JSON, rendered HTML, or raw (unrendered) HTML (planned). #### JSON @@ -106,8 +107,10 @@ If you set the output to JSON, your completion will be parsed into an object wit #### HTML HTML is available after processing by rendering and JavaScript engines or in the raw form sent by -the chatbot. +the chatbot (planned). ## Additional examples +### Cachebusting + diff --git a/web-render/batching.mdx b/web-render/batching.mdx new file mode 100644 index 0000000..d1963b8 --- /dev/null +++ b/web-render/batching.mdx @@ -0,0 +1,57 @@ +--- +title: Bulk processing +icon: list-check +iconType: light +description: Make massively parallel requests. +--- + +import { apiEndpoint } from '/snippets/whitelabel/config.mdx'; +import Terms from '/snippets/whitelabel/search/batches/terms.mdx'; +import Prompts from '/snippets/whitelabel/ai/batches/prompts.mdx'; +import Urls from '/snippets/whitelabel/browser/batches/urls.mdx'; +import Results from '/snippets/whitelabel/search/batches/id.mdx'; +import Completions from '/snippets/whitelabel/ai/batches/id.mdx'; +import Content from '/snippets/whitelabel/browser/batches/id.mdx'; + +## Batch jobs + +Each service has a batch endpoint that accepts a JSON array of up to **1,000 requests** in a `POST` +body: + + + + + + + + + + + + + +Search, AI, or +browsing and +geotargeting parameters can be included in the body. In response, +the API will provide a job identifier and confirmation of the request count: + +```json +{ + "id": "b3829f53-abc9-4e62-8a65-2d9359d586d6", + "count": 37 +} +``` + +The job status can be requested any time thereafter by passing back the ID: + + + + + + + + + + + + diff --git a/web-render/browser.mdx b/web-render/browser.mdx index c03c424..90aa5f6 100644 --- a/web-render/browser.mdx +++ b/web-render/browser.mdx @@ -10,9 +10,15 @@ import { Reference } from '/snippets/whitelabel/reference.mdx'; import { Autoscaling } from '/snippets/whitelabel/autoscaling.mdx'; import Authentication from '/snippets/whitelabel/authentication.mdx'; import Url from '/snippets/whitelabel/browser/url.mdx'; +import Puppeteer from '/snippets/whitelabel/browser/cdp/puppeteer.mdx'; +import Playwright from '/snippets/whitelabel/browser/cdp/playwright.mdx'; +import Difficulty from '/snippets/whitelabel/browser/cdp/difficulty.mdx'; +import Goto from '/snippets/whitelabel/browser/cdp/goto.mdx'; +import Rest2Cdp from '/snippets/whitelabel/browser/cdp/rest2cdp.mdx'; import Device from '/snippets/whitelabel/browser/device.mdx'; +import CdpDevice from '/snippets/whitelabel/browser/cdp/device.mdx'; import Expiration from '/snippets/whitelabel/browser/expiration.mdx'; -import Session from '/snippets/whitelabel/browser/session.mdx'; +import E2E from '/snippets/whitelabel/browser/cdp/e2e.mdx'; import Devices from '/snippets/whitelabel/browser/devices.mdx'; @@ -22,13 +28,15 @@ import Devices from '/snippets/whitelabel/browser/devices.mdx'; **{companyName}'s** browser service navigates intelligently on your behalf, rendering JavaScript, solving [captchas](https://www.ibm.com/topics/captcha), and retrying failed requests. The service has a RESTful interface that accepts `GET` requests at -**https://‍{apiEndpoint}/browser**. +**https://‍{apiEndpoint}/browser** and a +[Chrome DevTools Protocol (CDP) interface](#cdp-interaction) for controlling browser navigation +yourself that accepts WebSocket connections at **wss://{apiEndpoint}/browser**. -Webpages can be localized with geotargeting parameters. They're -retrieved in real time by default or optionally queued for subsequent -retrieval. Up to **3 minutes** is allotted per real-time API call to accommodate -captcha-solving, multiple retries, and other mitigations. Usage data is -published regularly. +Webpages can be localized with geotargeting parameters. Those +requested via REST are retrieved in real time by default or optionally queued for subsequent retrieval. Up to **3 minutes** is allotted per real-time API +call to accommodate captcha-solving, multiple retries, and other mitigations. Usage data is published regularly. If a site you're targeting remains blocked, even with different browsing params, -### Browsing parameters +### REST parameters Besides the [geotargeting and scheduling params linked above](#service-usage), required and optional -browsing params can be added in a +REST params can be added in a [standard query string](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_URL#parameters). See our rate card for the prices of premium params. The keys and values **{companyName}** supports are as follows: -| Key | Required | Premium | Value | -| :----------- | :------- | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `url` | ✅ | ⬜ | The URL of the page to browse; any unsafe characters require [URL encoding](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding) | -| `difficulty` | ⬜ | ✅ | The difficulty pool to attempt to access the URL from, `low`, `medium`, or `high` (planned); `low` is the default difficulty | -| `speed` | ⬜ | ✅ | The speed to attempt to access the URL at, `light`, `ridiculous`, or `ludicrous` (planned), where `ridiculous` is 30 percent faster on average than `light` speed; `light` is the default speed | -| `device` | ⬜ | ⬜ | The name as returned by the [devices resource](#device-emulation) of the device to emulate browsing on (these names are case insensitive but must include form- or URL-encoded spaces and punctuation marks); device emulation is unused by default | -| `captcha` | ⬜ | ⬜ | The intended resolution of any detected captcha, `solved`, `ignored`, or `rejected`, where `rejected` results in a `403` response; `solved` is the default captcha resolution | -| `readiness` | ⬜ | ⬜ | The standard ready event to await before snapshotting browsed content, `load` or `domcontentloaded`; `load` is the default ready event | -| `delay` | ⬜ | ⬜ | The number of supplemental seconds to delay before snapshotting browsed content, from `.1` to `10` inclusive; no delay is used by default | -| `format` | ⬜ | ⬜ | The format to output to, `rendered`, `raw`, or `markdown` (see the [section below](#response-format)); `rendered` is the default format | -| `expiration` | ⬜ | ⬜ | The age in days of when to consider cached content expired, where `0` disables caching; `1` is the default number of days before expiration | +| Key | Required | Premium | Value | +| :----------- | :------- | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `url` | ✅ | ⬜ | The URL of up to 2,047 characters of the page to browse; any unsafe characters require [URL encoding](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding) | +| `difficulty` | ⬜ | ✅ | The difficulty pool to attempt to access the URL from, `low`, `medium`, or `high` (planned); `low` is the default difficulty | +| `speed` | ⬜ | ✅ | The speed to attempt to access the URL at, `light`, `ridiculous`, or `ludicrous` (planned), where `ridiculous` is 30 percent faster on average than `light` speed; `light` is the default speed | +| `device` | ⬜ | ⬜ | The name as returned by the [devices resource](#device-emulation) of the device to emulate browsing on (these names are case insensitive but must include form- or URL-encoded spaces and punctuation marks); device emulation is unused by default | +| `session` | ⬜ | ⬜ | Any unique identifier of up to 255 characters (regardless of character encoding); **{companyName}** will make best efforts to route calls in the same session to the same egress node for up to 12 minutes | +| `captcha` | ⬜ | ⬜ | The intended resolution of any detected captcha, `solved`, `ignored`, or `rejected`, where `rejected` results in a `403` response; `solved` is the default captcha resolution | +| `readiness` | ⬜ | ⬜ | The standard ready event to await before snapshotting browsed content, `load` or `domcontentloaded`; `load` is the default ready event | +| `delay` | ⬜ | ⬜ | The number of supplemental seconds to delay before snapshotting browsed content, from `.1` to `10` inclusive; no delay is used by default | +| `format` | ⬜ | ⬜ | The format to output to, `rendered`, `raw`, or `markdown` (see the [section below](#response-format)); `rendered` is the default format | +| `expiration` | ⬜ | ⬜ | The age in days of when to consider cached content expired, where `0` disables caching; `1` is the default number of days before expiration | +| `callback` | ⬜ | ⬜ | The encoded HTTP or HTTPS callback URL or Amazon SQS queue URL or ARN of up to 2,047 characters to notify when the (prerequisite) asynchronous content has been retrieved; any SQS queue must grant `sqs:SendMessage` permission to the `arn:aws:iam::180363035301:role/api-instance` AWS principal | + +### CDP interaction + +If your use case involves interacting with not just reading pages, you can connect +[Puppeteer](https://pptr.dev/), [Playwright](https://playwright.dev/), or +[another CDP-compatible automation framework](https://github.com/ChromeDevTools/awesome-chrome-devtools#libraries-for-driving-the-protocol-or-a-layer-above) +to the browser service: + + + + + + + +The connection string takes geotargeting params and a subset of the [REST params](#rest-parameters), +namely `difficulty`, `device`, and `session`: + + + +After connecting, most of your framework's API (see the [Puppeteer reference](https://pptr.dev/api), +[Playwright reference](https://playwright.dev/docs/api/class-playwright), et cetera) will be +available: + + + +CDP use is metered by time, so you should disconnect from the service when done by calling +`browser.disconnect()` (Puppeteer), `browser.close()` (Playwright), or the equivalent. + +### Protocol mixture + +You can control costs by mixing REST requests and CDP use within a sticky browser session. E.g., you +may want to prepare a page for interaction over REST then interact with the page over CDP: + + + + + +To hand off in reverse, from CDP to REST, call your disconnect method first. ### Device emulation -The `device` param lets you fetch device-specific content, rather than the default desktop content. +The `device` param lets you browse device-specific content, rather than the default desktop content. For a list of supported smartphone and tablet devices, make a request with your API token and no params to **https://‍{apiEndpoint}/browser/devices**: @@ -81,24 +129,25 @@ The API will return JSON that contains an alphabetized array of device names: ] ``` -Then, pass your device name of choice into your browsing request: +Then, pass your device name of choice into your browsing request or connection: -### Sticky sessions - -To reuse a browser session across requests, set a cookie named `session`: - - - -The cookie value can be any unique identifier of up to **255 characters** (regardless of character -encoding) and **{companyName}** will make best efforts to route calls in the same session to the -same egress node for up to **12 minutes**. + ### Response format -Pages are returned as rendered HTML, raw (unrendered) HTML, or Markdown optimized for LLM prompts. +Read-only pages are returned as rendered HTML, raw (unrendered) HTML, or Markdown optimized for LLM +prompts. ## Additional examples +### Cachebusting + + +### End-to-end Playwright + + + + diff --git a/web-render/geotargeting.mdx b/web-render/geotargeting.mdx index 0647226..3250b37 100644 --- a/web-render/geotargeting.mdx +++ b/web-render/geotargeting.mdx @@ -16,11 +16,11 @@ Every HTTP request can be routed through one of more than 190 countries, by subd - + - + diff --git a/web-render/openapi.json b/web-render/openapi.json index 57cf824..7d67b6d 100644 --- a/web-render/openapi.json +++ b/web-render/openapi.json @@ -11,14 +11,34 @@ "/search": { "get": { "summary": "Results", - "description": "Retrieve search results or queue results for later retrieval.", + "description": "Retrieve search results or queue a search for later retrieval.", "parameters": [ + { + "name": "id", + "description": "The identifier returned by this endpoint of the queued search to retrieve; if given, all other params are ignored; either an ID or terms are required.", + "schema": { + "type": "string", + "format": "uuid", + "example": "078fd246-f0f7-44a0-aabb-cadd7b12454f" + }, + "in": "query" + }, { "name": "terms", - "description": "The broad or exact word or phrase of up to 255 characters to query (e.g., `foo bar baz` or `\"foo bar baz\"`); the terms require [form or URL encoding](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding) (with any space character being replaced by a `+` character or `%20` sequence).", - "schema": { "type": "string", "example": "foo bar baz" }, - "in": "query", - "required": true + "description": "The broad or exact word or phrase to query (e.g., `foo bar baz` or `\"foo bar baz\"`); the terms require [form or URL encoding](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding) (with any space character being replaced by a `+` character or `%20` sequence); either terms or an ID are required.", + "schema": { "type": "string", "maxLength": 255, "example": "foo bar baz" }, + "in": "query" + }, + { + "name": "engine", + "description": "The search engine to use.", + "schema": { + "type": "string", + "enum": ["google", "bing (coming soon)"], + "default": "google", + "example": "google" + }, + "in": "query" }, { "name": "serps", @@ -44,6 +64,12 @@ "schema": { "type": "integer", "minimum": 0, "maximum": 100, "example": null }, "in": "query" }, + { + "name": "device", + "description": "The name as returned by the [devices resource](search/devices) of the device to emulate searching on (these names are case insensitive but must include form- or URL-encoded spaces and punctuation marks); device emulation is unused by default.", + "schema": { "type": "string", "example": null }, + "in": "query" + }, { "name": "country", "description": "The [two-letter ISO code](https://www.iso.org/obp/ui/#search/code) of the country to search from (these codes are case insensitive); a random country is used by default.", @@ -86,7 +112,8 @@ "schema": { "type": "string", "format": "uri", - "example": "https://www.google.com/search?q=foo+bar+baz&hl=fr&gl=fr&ie=UTF-8" + "maxLength": 2047, + "example": "https%3A%2F%2Fwww.google.com%2Fsearch%3Fq%3Dfoo%2Bbar%2Bbaz%26hl%3Dfr%26gl%3Dfr%26ie%3DUTF-8" }, "in": "query" }, @@ -104,16 +131,17 @@ }, { "name": "mode", - "description": "The synchronous or asynchronous mode of results retrieval (see the [async resource](search/results)).", + "description": "The synchronous or asynchronous mode of results retrieval (retrieve async results by providing the returned ID).", "schema": { "$ref": "#/components/schemas/Mode" }, "in": "query" }, { "name": "callback", - "description": "The HTTP or HTTPS callback URL or Amazon SQS queue URL or ARN to notify when the (prerequisite) asynchronous results have been retrieved.", + "description": "The encoded HTTP or HTTPS callback URL or Amazon SQS queue URL or ARN to notify when the (prerequisite) async results have been retrieved; any SQS queue must grant `sqs:SendMessage` permission to the `arn:aws:iam::180363035301:role/api-instance` AWS principal.", "schema": { "type": "string", - "example": "https://webhook.site/02e249f8-1faf-4fab-bcf5-78ce683e85a8" + "maxLength": 2047, + "example": "https%3A%2F%2Fwebhook.site%2F02e249f8-1faf-4fab-bcf5-78ce683e85a8" }, "in": "query" } @@ -124,20 +152,34 @@ "content": { "text/html": { "schema": { "type": "string" } } } }, "202": { - "description": "A job identifier.", + "description": "A job identifier or the search status.", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "id": { - "description": "The identifier to retrieve the queued search with.", - "type": "string", - "format": "uuid", - "example": "078fd246-f0f7-44a0-aabb-cadd7b12454f" + "oneOf": [ + { + "type": "object", + "properties": { + "id": { + "description": "The identifier to retrieve the queued search with.", + "type": "string", + "format": "uuid", + "example": "078fd246-f0f7-44a0-aabb-cadd7b12454f" + } + }, + "required": ["id"] + }, + { + "type": "object", + "properties": { + "status": { + "description": "The status of the queued search.", + "allOf": [{ "$ref": "#/components/schemas/Status" }] + } + }, + "required": ["status"] } - }, - "required": ["id"] + ] } } } @@ -155,7 +197,7 @@ "/search/results": { "get": { "summary": "Async results", - "description": "Retrieve the results or status of a queued search.", + "description": "Retrieve the results or status of a queued search – use `GET /search?id=...`.", "parameters": [ { "name": "id", @@ -171,12 +213,9 @@ ], "responses": { "200": { - "description": "The search results.", - "content": { "text/html": { "schema": { "type": "string" } } } - }, - "202": { - "description": "The search status.", + "description": "The search results or status.", "content": { + "text/html": { "schema": { "type": "string" } }, "application/json": { "schema": { "type": "object", @@ -193,22 +232,247 @@ }, "401": { "$ref": "#/components/responses/authenticationError" }, "403": { "$ref": "#/components/responses/authorizationError" }, + "402": { "$ref": "#/components/responses/creditsError" }, + "422": { "$ref": "#/components/responses/paramsError" }, + "500": { "$ref": "#/components/responses/unknownError" } + }, + "deprecated": true + } + }, + "/search/batches": { + "post": { + "summary": "Batch results", + "description": "Queue multiple searches for later retrieval.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "terms": { + "description": "The broad or exact words or phrases to query (e.g., `foo bar baz` or `\"foo bar baz\"`).", + "type": "array", + "items": { "type": "string", "maxLength": 255 }, + "minItems": 1, + "maxItems": 1000, + "example": ["foo bar baz"] + }, + "engine": { + "description": "The search engine to use.", + "type": "string", + "enum": ["google", "bing (coming soon)"], + "default": "google", + "example": "google" + }, + "serps": { + "description": "The number of results pages to fetch.", + "type": "integer", + "minimum": 1, + "maximum": 10, + "default": 1, + "example": 1 + }, + "size": { + "description": "The number of results per page to fetch; page size is unset by default.", + "type": "integer", + "minimum": 0, + "maximum": 100, + "example": null + }, + "offset": { + "description": "The number of initial results to skip; results aren’t offset by default.", + "type": "integer", + "minimum": 0, + "maximum": 100, + "example": null + }, + "device": { + "description": "The name as returned by the [devices resource](devices) of the device to emulate searching on (these names are case insensitive); device emulation is unused by default.", + "type": "string", + "example": null + }, + "country": { + "description": "The [two-letter ISO code](https://www.iso.org/obp/ui/#search/code) of the country to search from (these codes are case insensitive); a random country is used by default.", + "type": "string", + "example": null + }, + "subdivision": { + "description": "The alphanumeric second part (proceeding the separator) of a [first-level subdivision code](https://www.iso.org/obp/ui/#search/code) in the (prerequisite) country to search from (these codes are case insensitive); a random subdivision is used by default.", + "type": "string", + "example": null + }, + "city": { + "description": "The [commonly spelled name](https://www.geonames.org/) of the city in the (prerequisite) country to search from (these names are temporarily case sensitive); a random city is used by default.", + "type": "string", + "example": null + }, + "uule": { + "description": "The [proprietary encoded string](https://moz.com/blog/geolocation-the-ultimate-tip-to-emulate-local-search) for emulating the location to search from; if possible, the actual location is searched from not emulated; location emulation is unused by default.", + "type": "string", + "example": null + }, + "language": { + "description": "The commonly spelled name, [two-letter ISO code](https://www.loc.gov/standards/iso639-2/php/code_list.php), or [Google code](https://www.google.com/advanced_search) of the language to search in (these names and codes are case insensitive); the language is unset by default.", + "type": "string", + "example": null + }, + "display": { + "description": "The commonly spelled name, [two-letter ISO code](https://www.loc.gov/standards/iso639-2/php/code_list.php), or [Google code](https://www.google.com/advanced_search) of the search interface’s display language (these names and codes are case insensitive); the display language is unset by default or set to the language if given.", + "type": "string", + "example": null + }, + "urls": { + "description": "The URLs of the results pages to retrieve; if given, the URLs override any of the above params.", + "type": "array", + "items": { "type": "string", "format": "uri", "maxLength": 2047 }, + "minItems": 1, + "maxItems": 1000, + "example": ["https://www.google.com/search?q=foo+bar+baz&hl=fr&gl=fr&ie=UTF-8"] + }, + "awaiting": { + "description": "The lazy result features to wait to load; any AI overview, which can take significant time to generate, is awaited for a maximum of **1 minute**; multiple features can be provided by repeating the key; lazy results aren’t awaited by default.", + "type": "string", + "enum": ["ai", "answers", "ads"], + "example": "ai" + }, + "expiration": { + "description": "The age in days of when to consider cached results expired, where `0` disables caching.", + "type": "integer", + "minimum": 0, + "maximum": 1, + "default": 1, + "example": 0 + }, + "callback": { + "description": "The HTTP or HTTPS callback URL or Amazon SQS queue URL or ARN to notify when the batch results have been retrieved; any SQS queue must grant `sqs:SendMessage` permission to the `arn:aws:iam::180363035301:role/api-instance` AWS principal.", + "type": "string", + "maxLength": 2047, + "example": "https://webhook.site/02e249f8-1faf-4fab-bcf5-78ce683e85a8" + } + }, + "anyOf": [{ "required": ["terms"] }, { "required": ["urls"] }] + } + } + }, + "required": true + }, + "responses": { + "202": { + "description": "A job identifier and confirmation count.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "description": "The identifier to retrieve the batch searches with.", + "type": "string", + "format": "uuid", + "example": "a0482596-c2ad-445a-a435-727002156a20" + }, + "count": { + "description": "The number of queries in the batch as confirmed by the API.", + "type": "integer", + "minimum": 1, + "maximum": 1000, + "example": 1 + } + }, + "required": ["id", "count"] + } + } + } + }, + "401": { "$ref": "#/components/responses/authenticationError" }, + "403": { "$ref": "#/components/responses/authorizationError" }, + "402": { "$ref": "#/components/responses/creditsError" }, + "422": { "$ref": "#/components/responses/paramsError" }, + "500": { "$ref": "#/components/responses/unknownError" } + } + }, + "get": { + "summary": "Batch results", + "description": "Retrieve the status of batch searches.", + "parameters": [ + { + "name": "id", + "description": "The identifier returned by the [batch search endpoint](../batching) of the bulk searches to retrieve.", + "schema": { + "type": "string", + "format": "uuid", + "example": "a0482596-c2ad-445a-a435-727002156a20" + }, + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "The batch status.", + "content": { + "application/json": { "schema": { "$ref": "#/components/schemas/BatchStatus" } } + } + }, + "401": { "$ref": "#/components/responses/authenticationError" }, + "403": { "$ref": "#/components/responses/authorizationError" }, + "402": { "$ref": "#/components/responses/creditsError" }, "422": { "$ref": "#/components/responses/paramsError" }, "500": { "$ref": "#/components/responses/unknownError" } } } }, + "/search/devices": { + "get": { + "summary": "Devices", + "description": "Retrieve supported device names.", + "responses": { + "200": { + "description": "The device names.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { "type": "string" }, + "example": [ + "Blackberry PlayBook", + "Blackberry PlayBook landscape", + "BlackBerry Z30", + "" + ] + } + } + } + }, + "401": { "$ref": "#/components/responses/authenticationError" }, + "403": { "$ref": "#/components/responses/authorizationError" }, + "402": { "$ref": "#/components/responses/creditsError" } + } + } + }, "/ai": { "get": { "summary": "Completion", - "description": "Retrieve an LLM completion or queue a completion for later retrieval.", + "description": "Retrieve an LLM completion or queue a conversation for later retrieval.", "parameters": [ + { + "name": "id", + "description": "The identifier returned by this endpoint of the queued conversation to retrieve; if given, all other params are ignored; either an ID or prompt is required.", + "schema": { + "type": "string", + "format": "uuid", + "example": "1851dab8-4619-409f-893f-47dd3a180bc3" + }, + "in": "query" + }, { "name": "prompt", - "description": "The question or instruction of up to 2,047 characters to use as a chat prompt; the prompt requires [form or URL encoding](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding) (with any space character being replaced by a `+` character or `%20` sequence).", - "schema": { "type": "string", "example": "best basketball shoes for 2026" }, - "in": "query", - "required": true + "description": "The question or instruction to use as a chat prompt; the prompt requires [form or URL encoding](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding) (with any space character being replaced by a `+` character or `%20` sequence); either a prompt or ID is required.", + "schema": { + "type": "string", + "maxLength": 2047, + "example": "best basketball shoes for 2026" + }, + "in": "query" }, { "name": "model", @@ -246,14 +510,14 @@ "in": "query" }, { - "name": "language (planned)", - "description": "The commonly spelled name or [two-letter ISO code](https://www.loc.gov/standards/iso639-2/php/code_list.php) of the language to chat in (these names and codes are case insensitive but required to include form- or URL-encoded spaces and punctuation marks); the language is unset by default.", + "name": "language", + "description": "[Planned] The commonly spelled name or [two-letter ISO code](https://www.loc.gov/standards/iso639-2/php/code_list.php) of the language to chat in (these names and codes are case insensitive but required to include form- or URL-encoded spaces and punctuation marks); the language is unset by default.", "schema": { "type": "string", "example": null }, "in": "query" }, { - "name": "display (planned)", - "description": "The commonly spelled name or [two-letter ISO code](https://www.loc.gov/standards/iso639-2/php/code_list.php) of the chat interface’s display language (these names and codes are case insensitive but required to include form- or URL-encoded spaces and punctuation marks); the display language is unset by default or set to the language if given.", + "name": "display", + "description": "[Planned] The commonly spelled name or [two-letter ISO code](https://www.loc.gov/standards/iso639-2/php/code_list.php) of the chat interface’s display language (these names and codes are case insensitive but required to include form- or URL-encoded spaces and punctuation marks); the display language is unset by default or set to the language if given.", "schema": { "type": "string", "example": null }, "in": "query" }, @@ -262,7 +526,7 @@ "description": "The format to output to.", "schema": { "type": "string", - "enum": ["json", "rendered", "raw"], + "enum": ["json", "rendered", "raw (planned)"], "default": "json", "example": "rendered" }, @@ -276,9 +540,19 @@ }, { "name": "mode", - "description": "The synchronous or asynchronous mode of completion retrieval (see the [async resource](ai/completions)).", + "description": "The synchronous or asynchronous mode of completion retrieval (retrieve an async completion by providing the returned ID).", "schema": { "$ref": "#/components/schemas/Mode" }, "in": "query" + }, + { + "name": "callback", + "description": "The encoded HTTP or HTTPS callback URL or Amazon SQS queue URL or ARN to notify when the (prerequisite) async completion has been retrieved; any SQS queue must grant `sqs:SendMessage` permission to the `arn:aws:iam::180363035301:role/api-instance` AWS principal.", + "schema": { + "type": "string", + "maxLength": 2047, + "example": "https%3A%2F%2Fwebhook.site%2F02e249f8-1faf-4fab-bcf5-78ce683e85a8" + }, + "in": "query" } ], "responses": { @@ -290,20 +564,34 @@ } }, "202": { - "description": "A job identifier.", + "description": "A job identifier or the conversation status.", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "id": { - "description": "The identifier to retrieve the queued conversation with.", - "type": "string", - "format": "uuid", - "example": "1851dab8-4619-409f-893f-47dd3a180bc3" + "oneOf": [ + { + "type": "object", + "properties": { + "id": { + "description": "The identifier to retrieve the queued conversation with.", + "type": "string", + "format": "uuid", + "example": "1851dab8-4619-409f-893f-47dd3a180bc3" + } + }, + "required": ["id"] + }, + { + "type": "object", + "properties": { + "status": { + "description": "The status of the queued conversation.", + "allOf": [{ "$ref": "#/components/schemas/Status" }] + } + }, + "required": ["status"] } - }, - "required": ["id"] + ] } } } @@ -320,8 +608,8 @@ }, "/ai/completions": { "get": { - "summary": "Async completions", - "description": "Retrieve the completion or status of a queued conversation.", + "summary": "Async completion", + "description": "Retrieve the completion or status of a queued conversation – use `GET /ai?id=...`.", "parameters": [ { "name": "id", @@ -337,31 +625,185 @@ ], "responses": { "200": { - "description": "The AI completion.", + "description": "The AI completion or status.", "content": { - "application/json": { "schema": { "$ref": "#/components/schemas/Completion" } }, + "application/json": { + "schema": { + "oneOf": [ + { "$ref": "#/components/schemas/Completion" }, + { + "type": "object", + "properties": { + "status": { + "description": "The status of the queued conversation.", + "allOf": [{ "$ref": "#/components/schemas/Status" }] + } + }, + "required": ["status"] + } + ] + } + }, "text/html": { "schema": { "type": "string" } } } }, + "401": { "$ref": "#/components/responses/authenticationError" }, + "403": { "$ref": "#/components/responses/authorizationError" }, + "402": { "$ref": "#/components/responses/creditsError" }, + "422": { "$ref": "#/components/responses/paramsError" }, + "500": { "$ref": "#/components/responses/unknownError" } + }, + "deprecated": true + } + }, + "/ai/batches": { + "post": { + "summary": "Batch completions", + "description": "Queue multiple LLM conversations for later retrieval.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "prompts": { + "description": "The questions or instructions to use as chat prompts.", + "type": "array", + "items": { "type": "string", "maxLength": 2047 }, + "minItems": 1, + "maxItems": 1000, + "example": [ + "Where can I buy a vintage guitar?", + "Help me find guitar repair shops nearby.", + "Do any local stores sell vinyl records?", + "[Additional prompts here]" + ] + }, + "model": { + "description": "The AI model to chat with.", + "type": "string", + "enum": ["chatgpt", "gemini", "perplexity", "copilot"], + "default": "chatgpt", + "example": "gemini" + }, + "device": { + "description": "The name as returned by the [devices resource](devices) of the device to emulate chatting on (these names are case insensitive but must include form- or URL-encoded spaces and punctuation marks); device emulation is unused by default.", + "type": "string", + "example": null + }, + "country": { + "description": "The [two-letter ISO code](https://www.iso.org/obp/ui/#search/code) of the country to chat from (these codes are case insensitive); a random country is used by default.", + "type": "string", + "example": null + }, + "subdivision": { + "description": "The alphanumeric second part (proceeding the separator) of a [first-level subdivision code](https://www.iso.org/obp/ui/#search/code) in the (prerequisite) country to chat from (these codes are case insensitive); a random subdivision is used by default.", + "type": "string", + "example": null + }, + "city": { + "description": "The [commonly spelled name](https://www.geonames.org/) of the city in the (prerequisite) country to chat from (these names are temporarily case sensitive and required to include form- or URL-encoded spaces and punctuation marks); a random city is used by default.", + "type": "string", + "example": null + }, + "language": { + "description": "[Planned] The commonly spelled name or [two-letter ISO code](https://www.loc.gov/standards/iso639-2/php/code_list.php) of the language to chat in (these names and codes are case insensitive but required to include form- or URL-encoded spaces and punctuation marks); the language is unset by default.", + "type": "string", + "example": null + }, + "display": { + "description": "[Planned] The commonly spelled name or [two-letter ISO code](https://www.loc.gov/standards/iso639-2/php/code_list.php) of the chat interface’s display language (these names and codes are case insensitive but required to include form- or URL-encoded spaces and punctuation marks); the display language is unset by default or set to the language if given.", + "type": "string", + "example": null + }, + "format": { + "description": "The format to output to.", + "type": "string", + "enum": ["json", "rendered", "raw (planned)"], + "default": "json", + "example": "rendered" + }, + "expiration": { + "description": "The age in days of when to consider a cached completion expired, where `0` disables caching.", + "type": "integer", + "minimum": 0, + "maximum": 1, + "default": 1, + "example": 0 + }, + "callback": { + "description": "The HTTP or HTTPS callback URL or Amazon SQS queue URL or ARN to notify when the batch completions have been retrieved; any SQS queue must grant `sqs:SendMessage` permission to the `arn:aws:iam::180363035301:role/api-instance` AWS principal.", + "type": "string", + "maxLength": 2047, + "example": "https://webhook.site/02e249f8-1faf-4fab-bcf5-78ce683e85a8" + } + }, + "required": ["prompts"] + } + } + }, + "required": true + }, + "responses": { "202": { - "description": "The conversation status.", + "description": "A job identifier and confirmation count.", "content": { "application/json": { "schema": { "type": "object", "properties": { - "status": { - "description": "The status of the queued conversation.", - "allOf": [{ "$ref": "#/components/schemas/Status" }] + "id": { + "description": "The identifier to retrieve the batch conversations with.", + "type": "string", + "format": "uuid", + "example": "a0482596-c2ad-445a-a435-727002156a20" + }, + "count": { + "description": "The number of prompts in the batch as confirmed by the API.", + "type": "integer", + "minimum": 1, + "maximum": 1000, + "example": 37 } }, - "required": ["status"] + "required": ["id", "count"] } } } }, "401": { "$ref": "#/components/responses/authenticationError" }, "403": { "$ref": "#/components/responses/authorizationError" }, + "402": { "$ref": "#/components/responses/creditsError" }, + "422": { "$ref": "#/components/responses/paramsError" }, + "500": { "$ref": "#/components/responses/unknownError" } + } + }, + "get": { + "summary": "Batch completions", + "description": "Retrieve the status of batch conversations.", + "parameters": [ + { + "name": "id", + "description": "The identifier returned by the [batch AI endpoint](../batching) of the bulk conversations to retrieve.", + "schema": { + "type": "string", + "format": "uuid", + "example": "a0482596-c2ad-445a-a435-727002156a20" + }, + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "The batch status.", + "content": { + "application/json": { "schema": { "$ref": "#/components/schemas/BatchStatus" } } + } + }, + "401": { "$ref": "#/components/responses/authenticationError" }, + "403": { "$ref": "#/components/responses/authorizationError" }, + "402": { "$ref": "#/components/responses/creditsError" }, "422": { "$ref": "#/components/responses/paramsError" }, "500": { "$ref": "#/components/responses/unknownError" } } @@ -398,14 +840,33 @@ "/browser": { "get": { "summary": "Content", - "description": "Retrieve web content or queue content for later retrieval.", + "description": "Retrieve web content or queue a request for later retrieval; connect to `wss://render.joinmassive.com/browser` for CDP interaction.", + "x-websocket": { + "url": "wss://render.joinmassive.com/browser", + "protocol": "Chrome DevTools Protocol", + "description": "Interact with webpages by connecting Puppeteer, Playwright, or another CDP-compatible automation framework." + }, "parameters": [ + { + "name": "id", + "description": "The identifier returned by this endpoint of the queued request to retrieve; if given, all other params are ignored; either an ID or URL is required.", + "schema": { + "type": "string", + "format": "uuid", + "example": "21cb972e-0e0f-47bb-9ce9-65b99e9cee77" + }, + "in": "query" + }, { "name": "url", - "description": "The URL of the page to browse; any unsafe characters require [URL encoding](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding).", - "schema": { "type": "string", "format": "uri", "example": "https://example.com/" }, - "in": "query", - "required": true + "description": "The URL of the page to browse; any unsafe characters require [URL encoding](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding); either a URL or ID is required.", + "schema": { + "type": "string", + "format": "uri", + "maxLength": 2047, + "example": "https://example.com/" + }, + "in": "query" }, { "name": "difficulty", @@ -500,9 +961,19 @@ }, { "name": "mode", - "description": "The synchronous or asynchronous mode of content retrieval (see the [async resource](browser/content)).", + "description": "The synchronous or asynchronous mode of content retrieval (retrieve async content by providing the returned ID).", "schema": { "$ref": "#/components/schemas/Mode" }, "in": "query" + }, + { + "name": "callback", + "description": "The encoded HTTP or HTTPS callback URL or Amazon SQS queue URL or ARN to notify when the (prerequisite) async content has been retrieved; any SQS queue must grant `sqs:SendMessage` permission to the `arn:aws:iam::180363035301:role/api-instance` AWS principal.", + "schema": { + "type": "string", + "maxLength": 2047, + "example": "https%3A%2F%2Fwebhook.site%2F02e249f8-1faf-4fab-bcf5-78ce683e85a8" + }, + "in": "query" } ], "responses": { @@ -511,20 +982,34 @@ "content": { "text/html": { "schema": { "type": "string" } } } }, "202": { - "description": "A job identifier.", + "description": "A job identifier or the request status.", "content": { "application/json": { "schema": { - "type": "object", - "properties": { - "id": { - "description": "The identifier to retrieve the queued request with.", - "type": "string", - "format": "uuid", - "example": "21cb972e-0e0f-47bb-9ce9-65b99e9cee77" + "oneOf": [ + { + "type": "object", + "properties": { + "id": { + "description": "The identifier to retrieve the queued request with.", + "type": "string", + "format": "uuid", + "example": "21cb972e-0e0f-47bb-9ce9-65b99e9cee77" + } + }, + "required": ["id"] + }, + { + "type": "object", + "properties": { + "status": { + "description": "The status of the queued request.", + "allOf": [{ "$ref": "#/components/schemas/Status" }] + } + }, + "required": ["status"] } - }, - "required": ["id"] + ] } } } @@ -544,7 +1029,7 @@ "/browser/content": { "get": { "summary": "Async content", - "description": "Retrieve the content or status of a queued request.", + "description": "Retrieve the content or status of a queued request – use `GET /browser?id=...`.", "parameters": [ { "name": "id", @@ -560,12 +1045,9 @@ ], "responses": { "200": { - "description": "The request content.", - "content": { "text/html": { "schema": { "type": "string" } } } - }, - "202": { - "description": "The request status.", + "description": "The request content or status.", "content": { + "text/html": { "schema": { "type": "string" } }, "application/json": { "schema": { "type": "object", @@ -582,6 +1064,179 @@ }, "401": { "$ref": "#/components/responses/authenticationError" }, "403": { "$ref": "#/components/responses/authorizationError" }, + "402": { "$ref": "#/components/responses/creditsError" }, + "422": { "$ref": "#/components/responses/paramsError" }, + "500": { "$ref": "#/components/responses/unknownError" } + }, + "deprecated": true + } + }, + "/browser/batches": { + "post": { + "summary": "Batch content", + "description": "Queue multiple web requests for later retrieval.", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "urls": { + "description": "The URLs of the pages to browse.", + "type": "array", + "items": { "type": "string", "format": "uri", "maxLength": 2047 }, + "minItems": 1, + "maxItems": 1000, + "example": [ + "https://guitars.com/", + "https://cartervintage.com/", + "https://musiccityvintageguitars.com/", + "[Additional URLs here]" + ] + }, + "difficulty": { + "description": "The difficulty pool to attempt to access the URLs from.", + "type": "string", + "enum": ["low", "medium", "high"], + "default": "low", + "example": "low" + }, + "speed": { + "description": "The speed to attempt to access the URLs at, where `ridiculous` is 30 percent faster on average than `light` speed.", + "type": "string", + "enum": ["light", "ridiculous", "ludicrous (planned)"], + "default": "light", + "example": "light" + }, + "device": { + "description": "The name as returned by the [devices resource](devices) of the device to emulate browsing on (these names are case insensitive); device emulation is unused by default.", + "type": "string", + "example": null + }, + "country": { + "description": "The [two-letter ISO code](https://www.iso.org/obp/ui/#search/code) of the country to browse from (these codes are case insensitive); a random country is used by default.", + "type": "string", + "example": null + }, + "subdivision": { + "description": "The alphanumeric second part (proceeding the separator) of a [first-level subdivision code](https://www.iso.org/obp/ui/#search/code) in the (prerequisite) country to browse from (these codes are case insensitive); a random subdivision is used by default.", + "type": "string", + "example": null + }, + "city": { + "description": "The [commonly spelled name](https://www.geonames.org/) of the city in the (prerequisite) country to browse from (these names are temporarily case sensitive); a random city is used by default.", + "type": "string", + "example": null + }, + "captcha": { + "description": "The intended resolution of any detected captcha, where `rejected` results in a `403` response.", + "type": "string", + "enum": ["solved", "ignored", "rejected"], + "default": "solved", + "example": "rejected" + }, + "readiness": { + "description": "The standard ready event to await before snapshotting browsed content.", + "type": "string", + "enum": ["load", "domcontentloaded"], + "default": "load", + "example": "load" + }, + "delay": { + "description": "The number of supplemental seconds to delay before snapshotting browsed content; no delay is used by default.", + "type": "number", + "minimum": 0.1, + "maximum": 10, + "example": null + }, + "format": { + "description": "The format to output to.", + "type": "string", + "enum": ["rendered", "raw", "markdown"], + "default": "rendered", + "example": "markdown" + }, + "expiration": { + "description": "The age in days of when to consider cached content expired, where `0` disables caching.", + "type": "integer", + "minimum": 0, + "maximum": 1, + "default": 1, + "example": 0 + }, + "callback": { + "description": "The HTTP or HTTPS callback URL or Amazon SQS queue URL or ARN to notify when the batch content has been retrieved; any SQS queue must grant `sqs:SendMessage` permission to the `arn:aws:iam::180363035301:role/api-instance` AWS principal.", + "type": "string", + "maxLength": 2047, + "example": "https://webhook.site/02e249f8-1faf-4fab-bcf5-78ce683e85a8" + } + }, + "required": ["urls"] + } + } + }, + "required": true + }, + "responses": { + "202": { + "description": "A job identifier and confirmation count.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "description": "The identifier to retrieve the batch content with.", + "type": "string", + "format": "uuid", + "example": "a0482596-c2ad-445a-a435-727002156a20" + }, + "count": { + "description": "The number of requests in the batch as confirmed by the API.", + "type": "integer", + "minimum": 1, + "maximum": 1000, + "example": 37 + } + }, + "required": ["id", "count"] + } + } + } + }, + "401": { "$ref": "#/components/responses/authenticationError" }, + "403": { "$ref": "#/components/responses/authorizationError" }, + "402": { "$ref": "#/components/responses/creditsError" }, + "422": { "$ref": "#/components/responses/paramsError" }, + "500": { "$ref": "#/components/responses/unknownError" } + } + }, + "get": { + "summary": "Batch content", + "description": "Retrieve the status of batch requests.", + "parameters": [ + { + "name": "id", + "description": "The identifier returned by the [batch browser endpoint](../batching) of the bulk requests to retrieve.", + "schema": { + "type": "string", + "format": "uuid", + "example": "a0482596-c2ad-445a-a435-727002156a20" + }, + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "The batch status.", + "content": { + "application/json": { "schema": { "$ref": "#/components/schemas/BatchStatus" } } + } + }, + "401": { "$ref": "#/components/responses/authenticationError" }, + "403": { "$ref": "#/components/responses/authorizationError" }, + "402": { "$ref": "#/components/responses/creditsError" }, "422": { "$ref": "#/components/responses/paramsError" }, "500": { "$ref": "#/components/responses/unknownError" } } @@ -626,9 +1281,10 @@ "type": "object", "properties": { "email": { - "description": "The email address of the user to create an account for; the address is case insensitive and can be up to 255 characters, regardless of character encoding.", + "description": "The email address of the user to create an account for; the address is case insensitive and can be in any character encoding.", "type": "string", "format": "email", + "maxLength": 255, "example": "user@example.com" }, "credits": { @@ -1052,7 +1708,7 @@ "engine": { "description": "The queried search engine.", "type": "string", - "enum": ["google"], + "enum": ["google", "bing (coming soon)"], "example": "google" }, "terms": { @@ -1189,10 +1845,10 @@ "section": { "$ref": "#/components/schemas/Section" }, "feature": { "type": "integer", "minimum": 1 }, "position": { "type": "integer", "minimum": 1 }, - "url": { "type": "string" }, + "url": { "type": "string", "format": "uri" }, "title": { "type": "string" }, "site": { "type": "string" }, - "visibleUrl": { "type": "string" }, + "visibleUrl": { "type": "string", "format": "uri" }, "snippet": { "type": "string" }, "sitelinks": { "type": "array", "items": { "$ref": "#/components/schemas/Sitelink" } } }, @@ -1245,7 +1901,7 @@ "type": "object", "properties": { "position": { "type": "integer", "minimum": 1 }, - "url": { "type": "string" }, + "url": { "type": "string", "format": "uri" }, "title": { "type": "string" }, "snippet": { "type": "string" } }, @@ -1291,13 +1947,13 @@ "type": "string", "example": "
- - Generate popular LLM completions. - - - Unblock difficult-to-crawl websites. - - - Extract top real-time search results. - - - -## Configuration - -Options that apply across every endpoint. - - - - Make requests from anywhere. - - - Defer responses for later retrieval. - - - -## Managing your account - - - - Understand API credits and billing. - - - Track API usage and performance. - - - -## API reference - -Prefer to jump straight to the spec? The [API reference](/web-render/reference/ai) documents -every parameter, response field, and status code for each endpoint. diff --git a/web-render/reference/ai/batches.mdx b/web-render/reference/ai/batches.mdx new file mode 100644 index 0000000..7bb8f6f --- /dev/null +++ b/web-render/reference/ai/batches.mdx @@ -0,0 +1,3 @@ +--- +openapi: post /ai/batches +--- diff --git a/web-render/reference/ai/status.mdx b/web-render/reference/ai/status.mdx new file mode 100644 index 0000000..2d1e3a0 --- /dev/null +++ b/web-render/reference/ai/status.mdx @@ -0,0 +1,3 @@ +--- +openapi: get /ai/batches +--- diff --git a/web-render/reference/browser/batches.mdx b/web-render/reference/browser/batches.mdx new file mode 100644 index 0000000..62c66f8 --- /dev/null +++ b/web-render/reference/browser/batches.mdx @@ -0,0 +1,3 @@ +--- +openapi: post /browser/batches +--- diff --git a/web-render/reference/browser/status.mdx b/web-render/reference/browser/status.mdx new file mode 100644 index 0000000..1a2bd92 --- /dev/null +++ b/web-render/reference/browser/status.mdx @@ -0,0 +1,3 @@ +--- +openapi: get /browser/batches +--- diff --git a/web-render/reference/search/batches.mdx b/web-render/reference/search/batches.mdx new file mode 100644 index 0000000..949e2ca --- /dev/null +++ b/web-render/reference/search/batches.mdx @@ -0,0 +1,3 @@ +--- +openapi: post /search/batches +--- diff --git a/web-render/reference/search/devices.mdx b/web-render/reference/search/devices.mdx new file mode 100644 index 0000000..6846d93 --- /dev/null +++ b/web-render/reference/search/devices.mdx @@ -0,0 +1,3 @@ +--- +openapi: get /search/devices +--- diff --git a/web-render/reference/search/status.mdx b/web-render/reference/search/status.mdx new file mode 100644 index 0000000..ba759ff --- /dev/null +++ b/web-render/reference/search/status.mdx @@ -0,0 +1,3 @@ +--- +openapi: get /search/batches +--- diff --git a/web-render/scheduling.mdx b/web-render/scheduling.mdx index cac403f..03390c6 100644 --- a/web-render/scheduling.mdx +++ b/web-render/scheduling.mdx @@ -6,9 +6,9 @@ description: Defer responses for later retrieval. --- import { apiEndpoint } from '/snippets/whitelabel/config.mdx'; -import Search from '/snippets/whitelabel/search/mode.mdx'; -import Ai from '/snippets/whitelabel/ai/mode.mdx'; -import Browser from '/snippets/whitelabel/browser/mode.mdx'; +import Terms from '/snippets/whitelabel/search/mode.mdx'; +import Prompt from '/snippets/whitelabel/ai/mode.mdx'; +import Url from '/snippets/whitelabel/browser/mode.mdx'; import Results from '/snippets/whitelabel/search/id.mdx'; import Completion from '/snippets/whitelabel/ai/id.mdx'; import Content from '/snippets/whitelabel/browser/id.mdx'; @@ -17,11 +17,17 @@ import Content from '/snippets/whitelabel/browser/id.mdx'; An API call that includes the `mode=async` key-value pair will be satisfied asynchronously: - + - + + + + - + + + + In response, the API will provide a JSON job identifier: @@ -29,23 +35,20 @@ In response, the API will provide a JSON job identifier: { "id": "078fd246-f0f7-44a0-aabb-cadd7b12454f" } ``` -```json -{ "id": "1851dab8-4619-409f-893f-47dd3a180bc3" } -``` - -```json -{ "id": "21cb972e-0e0f-47bb-9ce9-65b99e9cee77" } -``` - -The job results, completion, or content or job status can be requested at any time thereafter by -passing the identifier to **https://‍{apiEndpoint}/search/results**, -**https://‍{apiEndpoint}/ai/completions**, or **https://‍{apiEndpoint}/browser/content**: +The job results, completion, or content or job status can be requested any time thereafter by +passing back the ID: - + + + + - + + + + The results, completion, or content, if ready, will be returned in the same format as synchronous results, a @@ -45,16 +47,41 @@ The keys and values **{companyName}** supports are as follows: | Key | Required | Value | | :----------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `terms` | ✅ | The broad or exact word or phrase of up to 255 characters to query (e.g., `foo bar baz` or `"foo bar baz"`); the terms require [form or URL encoding](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding) (with any space character being replaced by a `+` character or `%20` sequence) | +| `engine` | ⬜ | The search engine to use, `google` or `bing` (coming soon); `google` is the default engine | | `serps` | ⬜ | The number of results pages to retrieve, from `1` to `10` inclusive; `1` is the default count | | `size` | ⬜ | The number of results per page to retrieve, from `0` to `100` inclusive; page size is unset by default | | `offset` | ⬜ | The number of initial results to skip, from `0` to `100` inclusive; results aren't offset by default | +| `device` | ⬜ | The name as returned by the [devices resource](#device-emulation) of the device to emulate searching on (these names are case insensitive but must include form- or URL-encoded spaces and punctuation marks); device emulation is unused by default | | `uule` | ⬜ | The [proprietary encoded string](https://moz.com/blog/geolocation-the-ultimate-tip-to-emulate-local-search) for emulating the location to search from; if possible, the actual location is searched from not emulated; location emulation is unused by default | | `language` | ⬜ | The commonly spelled name, [two-letter ISO code](https://www.loc.gov/standards/iso639-2/php/code_list.php), or [Google code](https://www.google.com/advanced_search) of the language to search in (these names and codes are case insensitive but required to include form- or URL-encoded spaces and punctuation marks); the language is unset by default | | `display` | ⬜ | The commonly spelled name, [two-letter ISO code](https://www.loc.gov/standards/iso639-2/php/code_list.php), or [Google code](https://www.google.com/advanced_search) of the search interface's display language (these names and codes are case insensitive but required to include form- or URL-encoded spaces and punctuation marks); the display language is unset by default or set to the language if given | -| `url` | ⬜ | The encoded URL of the results page to retrieve; if given, the URL overrides any of the above params | +| `url` | ⬜ | The encoded URL of up to 2,047 characters of the results page to retrieve; if given, the URL overrides any of the above params | | `awaiting` | ⬜ | The lazy result features to wait to load, an `ai` overview, "People also ask" `answers`, or sponsored `ads`; any AI overview, which can take significant time to generate, is awaited for a maximum of **1 minute**; multiple features can be provided by repeating the key; lazy results aren't awaited by default | | `expiration` | ⬜ | The age in days of when to consider cached results expired, where `0` disables caching; `1` is the default number of days before expiration | -| `callback` | ⬜ | The HTTP or HTTPS callback URL or Amazon SQS queue URL or ARN to notify when the (prerequisite) asynchronous results have been retrieved | +| `callback` | ⬜ | The encoded HTTP or HTTPS callback URL or Amazon SQS queue URL or ARN of up to 2,047 characters to notify when the (prerequisite) asynchronous results have been retrieved; any SQS queue must grant `sqs:SendMessage` permission to the `arn:aws:iam::180363035301:role/api-instance` AWS principal | + +### Device emulation + +The `device` param lets you fetch device-specific results, rather than the default desktop results. +For a list of supported smartphone and tablet devices, make a request with your API token and no +params to **https://‍{apiEndpoint}/search/devices**: + + + +The API will return JSON that contains an alphabetized array of device names: + +```json +[ + "Blackberry PlayBook", + "Blackberry PlayBook landscape", + "BlackBerry Z30", + "[Remaining device names here]" +] +``` + +Then, pass your device name of choice into your search request: + + ### Response format @@ -64,10 +91,18 @@ feature infinite scrolling, the HTML of each page will be separated from the nex ## Additional examples +### Results omission + +### Alternative URL + +### Lazy results + +### Push notification +