API v3 is live and in beta: expect possible malfunctions and breaking changes in the coming days. If you find a bug, please report it to your Sillage contact.

Query content requests

Search the content requests of your workspace, a page at a time.

Returns the content requests of your workspace, most recent first, filtered by the JSON body you send. The list is paged with a cursor: send meta.cursor.next back as cursor until meta.cursor.has_more is false. It returns 25 content requests per page by default: set limit (up to 100) to get more or fewer.

Route

POST/api/v3/content-requests/query

Access modes

Use a workspace API key. The workspace is inferred from the key.

Authorization: Bearer sk_live_...

Body parameters

Every field is optional: an empty body returns the first page of every content request. A field that is not listed is refused with 422.

FieldTypeDescription
cursorstringThe meta.cursor.next of the previous response, to fetch the next page. Omit it for the first page. It only works with the filters it was issued for: reused with other filters, or sent empty, it is refused with 422. See Pagination.
limitintegerNumber of items per page, from 1 to 100. Defaults to 25.
created_at_fromstringOnly requests created at or after this moment. ISO 8601 date and time with a UTC offset, for example 2026-09-01T00:00:00Z. A date without a time is refused with 422. Both bounds are included.
created_at_tostringOnly requests created at or before this moment. ISO 8601 date and time with a UTC offset, for example 2026-09-01T00:00:00Z. A date without a time is refused with 422. Both bounds are included.
typestringOnly requests of this type: account_mapping or key_account_content.
statusesstring[]Only requests in one of these statuses: pending, in_progress, completed, failed. There is no default: when you leave it out, every request is returned, finished ones included.
company_idsinteger[]Only results whose company is one of these companies. Pass company IDs, as returned by Query companies. Between 1 and 100 values.
company_domainsstring[]Only results whose company has one of these website domains, for example acme.com. Between 1 and 100 values.
company_linkedin_handlesstring[]Only results whose company has one of these LinkedIn handles, the last part of the LinkedIn page address. Between 1 and 100 values.
company_linkedin_urlsstring[]Only results whose company has one of these LinkedIn page URLs. Between 1 and 100 values.

The four company filters add up: a result matches when its company is any of the company_ids, or has any of the domains, LinkedIn handles or LinkedIn URLs you send. A value that matches no company in your workspace matches nothing, so the answer is an empty list, never an error. The company filters and every other filter all have to match.

Requests are sorted from the newest to the oldest. Requests created at the same moment keep a stable order, so no request is skipped or repeated from one page to the next.

Example request

curl -X POST "https://api.getsillage.com/api/v3/content-requests/query" \
  -H "Authorization: Bearer $SILLAGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"limit":10,"type":"account_mapping","statuses":["pending","in_progress"],"company_domains":["acme.com","example.com"]}'

Success response

Status: 200 OK

{
  "data": [
    {
      "id": 43821,
      "type": "account_mapping",
      "status": "in_progress",
      "label": "Mapping the account",
      "failed_reason": null,
      "persona_ids": [12],
      "created_at": "2026-06-12T08:30:00.000Z",
      "updated_at": "2026-06-12T09:10:00.000Z",
      "company": {
        "id": 8421,
        "name": "Acme",
        "domain": "acme.com",
        "linkedin_url": "https://www.linkedin.com/company/acme",
        "linkedin_handle": "acme",
        "logo_url": "https://example.com/acme-logo.png"
      }
    },
    {
      "id": 43790,
      "type": "account_mapping",
      "status": "pending",
      "label": "Waiting to start",
      "failed_reason": null,
      "persona_ids": [12],
      "created_at": "2026-06-12T08:30:00.000Z",
      "updated_at": "2026-06-12T08:52:00.000Z",
      "company": {
        "id": 8421,
        "name": "Acme",
        "domain": "acme.com",
        "linkedin_url": "https://www.linkedin.com/company/acme",
        "linkedin_handle": "acme",
        "logo_url": "https://example.com/acme-logo.png"
      }
    }
  ],
  "meta": {
    "cursor": {
      "next": null,
      "has_more": false
    },
    "resolved_companies": [
      {
        "company": {
          "id": 8421,
          "name": "Acme",
          "domain": "acme.com",
          "linkedin_url": "https://www.linkedin.com/company/acme",
          "linkedin_handle": "acme",
          "logo_url": "https://example.com/acme-logo.png"
        },
        "matched_by": "company_domains",
        "identifier": "acme.com"
      },
      {
        "company": {
          "id": 9103,
          "name": "Example",
          "domain": "example.com",
          "linkedin_url": "https://www.linkedin.com/company/example",
          "linkedin_handle": "example",
          "logo_url": null
        },
        "matched_by": "company_domains",
        "identifier": "example.com"
      }
    ]
  }
}

When nothing matches, data is an empty array and meta.cursor.has_more is false.

Response fields

FieldTypeDescription
data[].idintegerID of the content request.
data[].typestringWhat the request does: account_mapping or key_account_content.
data[].statusstringWhere the request is: pending, in_progress, completed or failed. See Statuses.
data[].labelstringA short, readable description of the current step, for example Mapping the account, Account mapping failed, Gathering content failed or Completed. It is meant to be shown as is.
data[].failed_reasonstring or nullWhy a content request (key_account_content) failed, when its status is failed. Always null for an account_mapping request, and for any request that has not failed. See failed_reason.
data[].persona_idsinteger[]IDs of the personas the request maps people for, as returned by List personas. Empty when none applies.
data[].created_atstringWhen the request was created, in ISO 8601.
data[].updated_atstringWhen the request last changed, in ISO 8601.
data[].companyobject or nullThe company the request is about.
data[].company.idintegerID of the company in your workspace.
data[].company.namestring or nullName of the company.
data[].company.domainstring or nullWebsite domain of the company.
data[].company.linkedin_urlstring or nullLinkedIn page of the company.
data[].company.linkedin_handlestring or nullLinkedIn handle of the company, the last part of its LinkedIn page address.
data[].company.logo_urlstring or nullLogo of the company.
meta.cursor.nextstring or nullPass it as cursor to fetch the next page. null on the last page.
meta.cursor.has_morebooleantrue when more requests exist after this page, false on the last page.
meta.resolved_companiesarrayThe companies your company filters matched. See meta.resolved_companies.

Statuses

statusMeaning
pendingThe request is waiting to start.
in_progressThe request is being worked on.
completedThe request is finished.
failedThe request stopped without completing. failed_reason says why.

failed_reason

Why a content request (key_account_content) failed, when its status is failed. It is always null for an account_mapping request, even a failed one, and for every request that has not failed.

ValueMeaning
no_employee_resolvedNo employee matching your persona was found for this company.
persona_without_job_titlesYour persona has no job title: add one to map accounts.
missing_linkedin_targetThe company had no usable LinkedIn page to work from.
request_timed_outThe request took too long and was stopped.
insufficient_creditsYour workspace ran out of credits before the request could complete.
internal_errorThe request failed on our side. Contact support if it keeps failing.

meta.resolved_companies

Lists the companies your company filters matched, one entry per company and per filter value that matched it. It is an empty array when you send no company filter.

FieldTypeDescription
companyobjectThe matched company, as a summary: id (its ID in your workspace), name, domain, linkedin_url, linkedin_handle and logo_url.
matched_bystringThe filter that matched this company: company_ids, company_domains, company_linkedin_handles or company_linkedin_urls.
identifierstringThe value you sent in that filter, a domain, a handle, a URL, or a company ID as a string.

Errors

StatusMeaning
401The API key is missing or invalid.
422The body is not valid: an unknown field, a value that is not allowed (for example a value in statuses that is not one of the four), a date without a time, a limit outside 1 to 100, or a cursor that was not issued to you by this endpoint, was issued for other filters, or is empty (errors then names cursor). A range that ends before it starts (created_at_from after created_at_to) is refused with the code invalid_date_range; errors.created_at_from says "must be on or before created_at_to".
429Rate limit exceeded.
500An unexpected server error occurred.

Error responses use RFC 9457 problem documents with Content-Type: application/problem+json. type is always about:blank; code tells one problem from another, detail says what went wrong this time, and errors names the field at fault. For example, with a statuses value that is not known:

{
  "type": "about:blank",
  "title": "Unprocessable Entity",
  "status": 422,
  "code": "invalid_body",
  "detail": "Invalid request body",
  "instance": "/api/v3/content-requests/query",
  "errors": {
    "statuses[0]": [
      "Invalid option: expected one of \"pending\"|\"in_progress\"|\"completed\"|\"failed\""
    ]
  }
}

On this page