Documentation
API ReferenceSubmit URLs
// Docs

Submit URLs

Submit a batch of URLs for processing. Requires the urls:write scope and an idempotency key.

POST /api/v1/urls accepts a batch of URLs, runs validation, and creates one task per accepted URL. The endpoint is idempotent: send a unique Idempotency-Key per logical request and the platform replays the stored response on a retry.

Request

FieldValue
MethodPOST
Path/api/v1/urls
AuthAuthorization: Bearer shl_live_<key> with scope urls:write
Required headerIdempotency-Key: <unique string, up to 255 characters>
BodyJSON object with a urls array
{
	"urls": [
		"https://example.com/page-a",
		"https://example.com/page-b"
	]
}

Limits: at most 100 URLs per request and about 900 KB of request body.

curl -X POST https://shoulu.co/api/v1/urls \
	-H "Authorization: Bearer shl_live_<key>" \
	-H "Idempotency-Key: batch-2026-10-25-001" \
	-H "Content-Type: application/json" \
	-d '{"urls":["https://example.com/page-a"]}'

Response

The endpoint returns 202 when at least part of the batch was accepted, and 429 when the whole batch hit a billing or account limit.

{
	"accepted": 1,
	"acceptedTasks": [
		{
			"id": "9b1d…",
			"url": "https://example.com/page-a",
			"status": "pending"
		}
	],
	"rejectedUpfront": [
		{
			"url": "ftp://bad.example",
			"reason": "unsupported_protocol"
		}
	],
	"batchError": null
}
  • accepted counts the tasks the platform created. It does not mean the provider accepted them or that search engines indexed the pages.
  • acceptedTasks[].id is the task ID to poll with GET /api/v1/tasks/{id}.
  • rejectedUpfront lists URLs that failed validation before task creation, with one reason per entry.
  • batchError is set when no tasks could be created. See Errors and limits for the values.

Rejection reasons

reasonCause
invalid_urlThe string does not parse as a URL
unsupported_protocolOnly http: and https: are accepted
invalid_domainThe hostname fails domain validation
blacklisted_domainThe domain is on the platform blacklist
duplicateAn identical URL is already pending for this account
over_limitThe batch exceeded a per-account cap after validation

Idempotency

The Idempotency-Key header is required. Keys are scoped to your API key and retained for 24 hours.

  • A retry with the same key and the same body returns the stored response.
  • A retry with the same key and a different body returns 409 idempotency conflict.
  • A retry while the first request still runs returns 425 with Retry-After: 30.

Use a fresh key per submission batch. Reusing a key by accident replays the old response instead of creating new tasks.