Todo lo que Mencoro monitoriza está disponible por HTTP: proyectos, consultas
monitorizadas, las capturas en bruto que hay detrás de cada comprobación y las
analíticas que se calculan a partir de ellas. 90 operaciones
, con una clave de API que creas tú.
El contrato OpenAPI es la fuente de verdad y es público: se lee sin clave. Cada
operación de esta página se genera a partir de ese contrato al compilar, así que no
puede describir una API que ya no existe.
Los ejemplos de esta página usan el cliente HTTP propio de cada lenguaje, así que
funcionan sin instalar nada. Los SDK son el atajo cuando el proyecto pasa de la primera
llamada.
Crear una clave
Las claves se crean desde tu cuenta, en
Claves de API dentro del menú de usuario. Cada clave lleva las capacidades
que puede ejercer y las organizaciones a las que llega.
La clave en claro se muestra una sola vez, al crearla, y nunca más. Guárdala
donde guardes cualquier otro secreto. Si la pierdes, revócala y crea otra; la revocación surte
efecto en la siguiente petición.
Una clave nunca amplía lo que su propietario puede hacer: solo restringe. Si tu rol en
una organización se reduce, o te sacan de ella, la clave pierde ese acceso de inmediato,
sin necesidad de revocarla ni de volver a emitirla.
Capacidades
Capacidad
Qué permite
read
Todos los listados y todas las operaciones de analítica. Es el suelo: la tiene
toda clave, de modo que una clave entregada para informes no puede modificar nada.
write
Proyectos, consultas monitorizadas, clústeres, competidores y trabajos de
descubrimiento; siempre dentro del rol que su propietario tenga en cada
organización.
organization:manage
Miembros, invitaciones y la organización en sí. Se pide explícitamente al crear la
clave: una clave que escribe datos de producto no toca la organización sin ella.
Tu primera petición
https://api.mencoro.com/api/v1/me devuelve el usuario al que pertenece la clave, más las capacidades
y el alcance de esa clave. Es la forma más rápida de confirmar que una clave funciona y de
ver a qué organizaciones llega.
curl -X GET "https://api.mencoro.com/api/v1/me" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Todo rechazo responde con el mismo sobre, y todos llevan un requestId.
Cítalo si escribes a soporte: identifica tu petición exacta.
{
"code": "validation_error",
"message": "The request failed validation.",
"requestId": "01a0c58a-3370-7170-acdb-a0a7b760bc83",
"details": {
"limit": [
{ "code": "out_of_range", "message": "\"limit\" must be between 1 and 100." }
]
}
}
details se indexa por campo, y cada entrada lleva uno de siete códigos:
missing_field, invalid_type, invalid_value,
invalid_uuid, invalid_email, out_of_range y
unknown_field. Un parámetro que no se reconoce se reporta en vez de
ignorarse, así que una errata en un filtro nunca te devuelve en silencio el conjunto sin
filtrar.
El code de primer nivel es el campo por el que ramificar, y es estable. Un rechazo
que esta API hace a propósito lleva nombre propio: organization_not_found,
project_is_archived, api_key_capability_required,
idempotency_key_reused, confirmation_required,
rate_limit_exceeded. Cada operación indica los que puede producir junto al
estado con el que llegan.
Cuando no aplica ninguno, el código es el propio estado: bad_request si el cuerpo
no es JSON, not_found si la ruta no existe,
method_not_allowed si el verbo no es el suyo. Cualquier 5xx
responde internal_error y nada más concreto: lo que falló por dentro está en
nuestros registros contra tu requestId, nunca en el cuerpo. Un código nunca
nombra el framework que hay debajo, así que no cambia cuando ese cambia.
Límites
600 peticiones por usuario y 300 por clave, cada 60 segundos. El techo por
usuario es el que manda: crear más claves reparte el mismo presupuesto, no lo amplía.
Al pasarte, la respuesta es 429 con una cabecera Retry-After en
segundos. Respétala en vez de reintentar de inmediato.
Las escrituras son idempotentes
Toda escritura exige una cabecera Idempotency-Key, de 8 a
255 caracteres ASCII imprimibles sin espacios; un UUID es la opción evidente.
Reutilízala al reintentar y se reproduce el resultado guardado en vez de ejecutar la
operación otra vez, de modo que una respuesta perdida no se convierte en un proyecto
duplicado ni en un segundo lote de consultas.
La clave queda asociada a la clave de API que la usó y ligada a la petición que
respondió primero: método, ruta y cuerpo. Reutilizarla para otra petición se rechaza con
idempotency_key_reused en vez de responder a la operación equivocada.
Los cambios en la organización se confirman
Algunas operaciones van más allá de tus propios datos: archivar una organización,
cambiar el rol de un miembro, invitar a alguien. Esas se hacen en dos llamadas. Primero
POST /api/v1/organization-operation-previews
, que informa exactamente de qué cambiaría la operación y devuelve un
confirmation.token
. Después la operación en sí, con ese token en
X-Mencoro-Confirmation
.
El token es de un solo uso, vale cinco minutos y está ligado a los efectos que declaró
la previsualización. Si entretanto la organización ganó un proyecto o perdió una
invitación, la llamada se rechaza con 409 en vez de hacer más de lo acordado.
Sin la cabecera responde 428.
Paginación, fechas y CSV
Los listados aceptan limit (20 por defecto, 100 como máximo) y
offset. Un límite por encima del máximo se
rechaza, nunca se recorta en silencio, así que la página que pides es
la página que recibes. total cuenta todo lo que casa con el filtro, no el tamaño
de la página.
Las fechas son YYYY-MM-DD y cubren días enteros en UTC.
Varios listados responden también text/csv si lo pides con una cabecera
Accept. Es la misma página de las mismas filas, codificada de otro modo: el
máximo de 100 filas se mantiene, porque es una página y no una exportación masiva.
También disponible por MCP
Si prefieres leer estos mismos datos desde un cliente de IA en lugar de desde tu código,
el servidor MCP de Mencoro los expone a Claude,
ChatGPT, Cursor y cualquier otro cliente que hable MCP. Los mismos datos, sin escribir código.
Los resúmenes de cada operación vienen del contrato OpenAPI, que la API publica en inglés.
Tracked Queries
GET /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries
Search a project's tracked queries
Minimum role: viewer.
One row per tracked query, a single keyword on a single engine in a single country, carrying the metrics of its most recent completed check. Filter by status, engine, country and a free-text search over the keyword, and sort by any of the returned metrics. Positions (lastSerpPosition, lastMentionPosition, lastLinkPosition, lastShoppingPosition) are 1-based ranks, so LOWER is better; lastShareOfVoice and lastPositivityIndex are percentages from 0 to 100, where HIGHER is better.
Every nullable field means "not known yet" rather than zero: a null position is a query with no data for that surface, a null lastPositivityIndex is a check with no mentions to score, and a null lastCheckedAt is a query that has never been checked. None of them is a score of zero.
This listing reads a projection refreshed by background subscribers, not the write model, so a tracked query created or changed moments ago may not appear here yet or may still show its previous settings. It catches up on its own; nothing is lost. If you need to read back what you just wrote, the creation response carries the new ids and the single tracked-query operation reads the write model directly.
total counts the tracked queries the filters match, not the rows on this page. A limit above the maximum is rejected, never clamped, and a filter this endpoint does not support is rejected rather than ignored.
Send Accept: text/csv to receive the same page as a CSV download instead of JSON: same filters, same authorization, same page window and the same maximum of 100 rows. It is this page in another format, not a bulk export, so a whole collection is still read by paging. The CSV carries no total, because a table whose every row is a record has nowhere to put one; read it from the JSON representation of the same request.
A list-valued field is joined into one cell with ; as a display projection. Parse the JSON if you need the structure. Cells beginning with =, +, - or @ are prefixed with an apostrophe so a spreadsheet treats them as text rather than running them as formulas.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
limit
query
integermin 1, max 100, default 20
Page size. A value above the maximum is rejected, never clamped.
POST /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries
Create tracked queries
Minimum role: manager.
Creates the cross product of queryTexts x engines x countries: three texts, two engines and two countries create twelve tracked queries, not three. At most 100 combinations per call. The organization must be active and the project must not be archived. Partial success: the response lists, per combination, either the id it was created under or why nothing was created for it, and the status code never reports item-level outcomes.
A combination the project already tracks is NOT created again and NOT re-identified. It appears under failed with tracked_query_already_exists, keeps the id it already had, and has any queryClusterIds in this request merged into it. Query text is normalised before it is compared and stored (lower-cased, whitespace collapsed, leading list markers stripped), so two texts differing only in those respects are one tracked query: the first of them owns the outcome and every later one appears under failed with duplicate_combination_in_request, naming the entry it repeats.
nPasses applies to AI engines only: google_serp and google_shopping rows are always created with one pass, whatever is sent. Google AI Mode is unavailable in a few countries and those combinations are reported under failed rather than created. Creating a tracked query does not run a check: the first check happens on the normal schedule for the checkFrequency chosen.
The Idempotency-Key header is required; a retry with the same key and the same body returns this same answer without creating anything again.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
string
A client-chosen key, unique per operation. Replaying it returns the first answer instead of creating anything again.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
queryTextsObligatorio
string[]
Prompts or keywords to track. Stored lower-cased with whitespace collapsed and leading list markers removed.
ISO 3166-1 alpha-2 countries each text is asked from.
locale
stringmin length 2, max length 2
ISO 639-1 language the queries are asked in. Omit it to ask the engine without a language.
checkFrequencyObligatorio
daily | weekly | monthly
How often every created query is checked.
nPassesObligatorio
integermin 1, max 10
Passes run per check. Applied to AI-engine combinations only: a non-AI engine is always created with 1, whatever is sent here.
queryClusterIdsObligatorio
string (uuid)[]
Clusters every created query joins. Must already exist in the project. A combination that is already tracked has these clusters merged into it.
Respuestas
200 Per-combination results. Read failed: a non-empty failed with a 200 is the normal partial-success answer.
400 The body was rejected, or the Idempotency-Key header is missing; details names the field
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization, project or query cluster the caller can access under these ids
409 The organization is archived, the project is archived, or the idempotency key was already used for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
422 A query cluster exists but belongs to another project
GET /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/{trackedQueryId}
Get a tracked query
Minimum role: viewer.
The configuration of one tracked query: the text sent to the engine, the engine, locale and country it is asked in, the clusters it belongs to, and how often it is checked. A lastCheckedAt of null means no check has completed yet. It is not a check that found nothing. A tracked query belonging to another project answers 404, the same answer an unknown id gets, so the API never confirms that an inaccessible tracked query exists.
Rank positions, share of voice and sentiment are not part of this response: they belong to a date window and are served by the analytics endpoints.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
trackedQueryIdObligatorio
path
string (uuid)
Must belong to the project in the path.
Respuestas
200 The tracked query
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization, project or tracked query the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/tracked-queries/$TRACKED_QUERY_ID" \
-H "Authorization: Bearer $MENCORO_API_KEY"
PUT /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/{trackedQueryId}/check-frequency
Change how often a tracked query is checked
Minimum role: manager.
Sets how often one tracked query is checked while it is active. The organization must be active and the project must not be archived. Setting the frequency it already has is accepted and changes nothing. This does NOT run a check, does not backfill history, and does not reschedule a check already in flight: the new cadence applies from the next time the query is considered.
A paused query keeps the setting but is not checked until it is resumed. A tracked query belonging to another project answers 404, the same answer an unknown id gets. The Idempotency-Key header is required; a retry with the same key and the same body returns this same answer without applying anything again.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
trackedQueryIdObligatorio
path
string (uuid)
Must belong to the project in the path.
Idempotency-KeyObligatorio
header
string
A client-chosen key, unique per operation. Replaying it returns the first answer instead of applying anything again.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
checkFrequencyObligatorio
daily | weekly | monthly
How often the query is checked while it is active.
Respuestas
200 The tracked query in its new state
400 The body was rejected, or the Idempotency-Key header is missing; details names the field
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization, project or tracked query the caller can access under these ids
409 The organization is archived, the project is archived, or the idempotency key was already used for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
PUT /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/{trackedQueryId}/clusters
Add a tracked query to clusters
Minimum role: manager.
Adds the tracked query to every cluster named in "queryClusterIds" and answers with the query in its new state. Membership is a set: a cluster the query already belongs to is skipped, not reported as an error, and the response still lists it. Clusters the query belongs to and this call does not name are left alone. This adds, it does not replace the membership.
Every cluster must belong to the project in the path; one that does not is rejected with its field named, and nothing is written. The "Idempotency-Key" header is required, and a repeat of the same key and body returns the recorded answer without adding anything again.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
trackedQueryIdObligatorio
path
string (uuid)
Must belong to the project in the path.
Idempotency-KeyObligatorio
header
string
A client-chosen key, unique per operation, so a lost response can be retried without repeating the write.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
queryClusterIdsObligatorio
string (uuid)[]
Ids of the query clusters. Duplicates are collapsed. Every id must belong to the project in the path.
Respuestas
200 The tracked query, including the clusters it now belongs to
400 The body was rejected: an unknown field, a malformed cluster id, a cluster outside this project, or a missing Idempotency-Key
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization, project or tracked query the caller can access under these ids
409 The organization is archived, the project is archived, the idempotency key was reused for a different body, or a cluster was deleted between validation and the write, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
Removes the tracked query from every cluster named in "queryClusterIds" and answers with the query in its new state. A cluster the query does not belong to is skipped, not reported as an error. Neither the clusters nor the tracked query are deleted: only the membership between them.
Every cluster must belong to the project in the path. NOTE: this DELETE requires a request body. Some HTTP client libraries and proxies strip bodies from DELETE, and a stripped body is refused with a validation error rather than interpreted as "remove all clusters". The "Idempotency-Key" header is required, and a repeat of the same key and body returns the recorded answer without removing anything again.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
trackedQueryIdObligatorio
path
string (uuid)
Must belong to the project in the path.
Idempotency-KeyObligatorio
header
string
A client-chosen key, unique per operation, so a lost response can be retried without repeating the write.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
queryClusterIdsObligatorio
string (uuid)[]
Ids of the query clusters. Duplicates are collapsed. Every id must belong to the project in the path.
Respuestas
200 The tracked query, including the clusters it still belongs to
400 The body was rejected or missing: an unknown field, a malformed cluster id, a cluster outside this project, a stripped DELETE body, or a missing Idempotency-Key
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization, project or tracked query the caller can access under these ids
409 The organization is archived, the project is archived, the idempotency key was reused for a different body, or a cluster was deleted between validation and the write, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
GET /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/{trackedQueryId}/mention-matches
List stored mention matches of a tracked query
Minimum role: viewer.
Text mentions across own brand and tracked or untracked competitors. Citation-only rows are excluded before pagination. Read mentionRelation to distinguish own brand from untracked competitors; a null competitorId alone does not classify the mention. Newest first by detection time, with an id tie-break.
Dates cover whole UTC days. Only the retained 16-month window is readable, including when dateFrom is omitted. Unknown filters are rejected. The total counts all matching rows before pagination. Send Accept: text/csv for the same bounded page and filters as CSV, with formula-safe cells and no total.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
trackedQueryIdObligatorio
path
string (uuid)
dateFrom
query
string (date)
Inclusive UTC day; defaults to the retention floor.
dateTo
query
string (date)
Inclusive UTC day.
limit
query
integermin 1, max 100, default 20
offset
query
integermin 0, default 0
sortOrder
query
asc | descdefault "desc"
Respuestas
200 Stored matches and total under the same filters
400 Invalid or unsupported query parameters
401 Missing or invalid API key
403 The key lacks the read capability
404 Organization, project or tracked query is not accessible
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/tracked-queries/$TRACKED_QUERY_ID/mention-matches" \
-H "Authorization: Bearer $MENCORO_API_KEY"
PUT /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/{trackedQueryId}/passes
Change how many passes a tracked query runs per check
Minimum role: manager.
Sets how many times one tracked query is asked per check. AI engines are not deterministic, so several passes are averaged; google_serp and google_shopping run a single pass and refuse any value above one with 409 n_passes_not_supported_for_engine. Setting the value back to 1 is always allowed.
The organization must be active and the project must not be archived. Setting the value it already has is accepted and changes nothing. This does NOT run a check and does not change history already captured: it applies from the next check. More passes cost proportionally more of the plan's check budget.
A tracked query belonging to another project answers 404, the same answer an unknown id gets. The Idempotency-Key header is required; a retry with the same key and the same body returns this same answer without applying anything again.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
trackedQueryIdObligatorio
path
string (uuid)
Must belong to the project in the path.
Idempotency-KeyObligatorio
header
string
A client-chosen key, unique per operation. Replaying it returns the first answer instead of applying anything again.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
nPassesObligatorio
integermin 1, max 10
Passes run per check. Only an AI engine accepts more than one.
Respuestas
200 The tracked query in its new state
400 The body was rejected, or the Idempotency-Key header is missing; details names the field
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization, project or tracked query the caller can access under these ids
409 The engine runs a single pass and cannot take more; or the organization or project is archived; or the idempotency key was already used for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
PUT /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/{trackedQueryId}/pause
Pause a tracked query
Minimum role: manager.
Stops the scheduler from checking this tracked query; it keeps its configuration, its clusters and every result already collected, and nothing is deleted. Pausing a query that is already paused succeeds and answers the same body. This is a PUT asserting a state, not a transition, so it is safe to repeat.
It does NOT cancel a check that is already running: a check in flight when the pause lands still completes and still consumes the budget unit it reserved. The request takes no body, and any field sent is rejected. Requires an Idempotency-Key header.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
trackedQueryIdObligatorio
path
string (uuid)
Must belong to the project in the path.
Idempotency-KeyObligatorio
header
string
Repeating a request with the same key answers with the first attempt's result instead of pausing again.
Respuestas
200 The tracked query, paused
400 The Idempotency-Key header is missing or malformed, or the request carried a body
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization, project or tracked query the caller can access under these ids
409 The organization or the project is archived, or the idempotency key was already used for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
POST /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/{trackedQueryId}/responses/{aiResponseId}/report
Report a problem with a captured AI answer
Minimum role: viewer. Deliberately lower than the other tracked-query writes, because a report changes nothing a viewer cannot already read.
The key still needs the "write" capability. The report is forwarded to the team that reviews the scrape run behind the capture; it does not change the capture, the tracked query, or any metric derived from them, and nothing in this API will show the report afterwards. A 200 means the report was accepted for review, not that anything was corrected, and there is no identifier to poll.
A capture that belongs to another tracked query or project answers 404, the same answer an unknown id gets. A capture that cannot be routed back to its scrape run answers 409 "ai_check_session_unavailable", and it cannot be reported. That code covers two moments, which behave differently for your key: when the capture carries no scrape run at all the refusal is decided BEFORE anything is sent, so the idempotency key is left unused and the same key answers the same way however often it is presented; when the review system itself rejects the run, its own retention having elapsed, the refusal comes after the forward was attempted, so the key is spent like any outcome we cannot confirm.
You can tell them apart without guessing: retry the same key, and a reply of "operation_outcome_uncertain" means the refusal came from the review system. Delivery is at-most-once: the "Idempotency-Key" header is required and a repeat of the same key and body returns the recorded answer, but a delivery whose outcome is unknown refuses replay on that key rather than risk filing the report twice.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
trackedQueryIdObligatorio
path
string (uuid)
Must belong to the project in the path.
aiResponseIdObligatorio
path
string (uuid)
A capture id from the AI responses listing. Must belong to the tracked query in the path.
Idempotency-KeyObligatorio
header
string
A client-chosen key, unique per report, so a lost response can be retried without filing the report twice.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
typeObligatorio
missed_mention | other
What is wrong with the capture.
comment
stringmax length 1000
Optional note for the reviewer, at most 1000 characters. An empty string is stored as no comment.
missedBrandNames
string[]
Brands the engine mentioned that the pipeline did not record. Most useful with type "missed_mention"; accepted with either. At most 50 distinct names of 255 characters each.
Respuestas
200 The report as accepted, in its normalised form
400 The body was rejected: an unknown field, a missing or unsupported "type", an over-long comment or brand name, or a missing Idempotency-Key
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization, project, tracked query or capture the caller can access under these ids
409 The organization is archived, the capture can no longer be routed back to its scrape run, the idempotency key was reused for a different body, or a previous attempt with this key ended with an unknown outcome
502 The review system could not be reached or refused the forward. Whether the report was filed is UNKNOWN: delivery is at-most-once and the failure can happen after the report was recorded upstream. This idempotency key will not replay; retrying with a new key may file the report twice.
PUT /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/{trackedQueryId}/resume
Resume a tracked query
Minimum role: manager.
Puts a paused tracked query back under the scheduler. Resuming a query that is already active succeeds and answers the same body. This is a PUT asserting a state, not a transition. It does NOT run a check: the query is checked when it next falls due under its own checkFrequency, and results collected while it was paused are unaffected.
Nothing is back-filled for the time it spent paused. The request takes no body, and any field sent is rejected. Requires an Idempotency-Key header.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
trackedQueryIdObligatorio
path
string (uuid)
Must belong to the project in the path.
Idempotency-KeyObligatorio
header
string
Repeating a request with the same key answers with the first attempt's result instead of resuming again.
Respuestas
200 The tracked query, active
400 The Idempotency-Key header is missing or malformed, or the request carried a body
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization, project or tracked query the caller can access under these ids
409 The organization or the project is archived, or the idempotency key was already used for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
GET /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/{trackedQueryId}/serp-matches
List stored serp matches of a tracked query
Minimum role: viewer.
Stored organic-search matches with the competitor attribution and position recorded at detection time. A null competitorId identifies the own-brand match. These are historical matches, not a reclassification using the current brand profile. Newest first by detection time, with an id tie-break.
Dates cover whole UTC days. Only the retained 16-month window is readable, including when dateFrom is omitted. Unknown filters are rejected. The total counts all matching rows before pagination. Send Accept: text/csv for the same bounded page and filters as CSV, with formula-safe cells and no total.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
trackedQueryIdObligatorio
path
string (uuid)
dateFrom
query
string (date)
Inclusive UTC day; defaults to the retention floor.
dateTo
query
string (date)
Inclusive UTC day.
limit
query
integermin 1, max 100, default 20
offset
query
integermin 0, default 0
sortOrder
query
asc | descdefault "desc"
Respuestas
200 Stored matches and total under the same filters
400 Invalid or unsupported query parameters
401 Missing or invalid API key
403 The key lacks the read capability
404 Organization, project or tracked query is not accessible
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/tracked-queries/$TRACKED_QUERY_ID/serp-matches" \
-H "Authorization: Bearer $MENCORO_API_KEY"
PUT /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/batch/check-frequency
Change how often several tracked queries are checked
Minimum role: manager.
Sets the same check frequency on every tracked query named in ids, at most 100 distinct ids per call. The organization must be active and the project must not be archived. Partial success: an id that is not a tracked query of this project, unknown, malformed, already deleted, or belonging to somewhere else, is reported under failed with tracked_query_not_found while the rest are changed, and the call still answers 200.
Nothing is rolled back because an item failed. Setting the frequency a query already has is accepted and changes nothing. This does NOT run a check and does not reschedule one already in flight. It never changes more than the ids it is given: there is no "change everything matching a filter" mode.
The Idempotency-Key header is required; a retry with the same key and the same body returns this same answer without applying anything again.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
string
A client-chosen key, unique per operation. Replaying it returns the first answer instead of applying anything again.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
idsObligatorio
string (uuid)[]
Ids of the tracked queries to change. Duplicates are collapsed.
checkFrequencyObligatorio
daily | weekly | monthly
How often each query is checked while it is active.
Respuestas
200 Per-id results. Read failed: a non-empty failed with a 200 is the normal partial-success answer.
400 The body was rejected, or the Idempotency-Key header is missing; details names the field
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The organization is archived, the project is archived, or the idempotency key was already used for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
PUT /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/batch/passes
Change how many passes several tracked queries run per check
Minimum role: manager.
Sets the same passes-per-check on every tracked query named in ids, at most 100 distinct ids per call. The organization must be active and the project must not be archived. Partial success, and two distinct reasons appear under failed: an id that is not a tracked query of this project answers tracked_query_not_found, and a google_serp or google_shopping query asked for more than one pass answers n_passes_not_supported_for_engine. Those engines run a single pass.
Both leave the rest of the batch changed and the call still answers 200. Setting the value back to 1 is always allowed, so a batch that lowers sampling never fails on engine grounds. This does NOT run a check and does not change history already captured. More passes cost proportionally more of the plan's check budget.
It never changes more than the ids it is given: there is no "change everything matching a filter" mode. The Idempotency-Key header is required; a retry with the same key and the same body returns this same answer without applying anything again.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
string
A client-chosen key, unique per operation. Replaying it returns the first answer instead of applying anything again.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
idsObligatorio
string (uuid)[]
Ids of the tracked queries to change. Duplicates are collapsed.
nPassesObligatorio
integermin 1, max 10
Passes run per check. Only an AI engine accepts more than one; a non-AI target is reported under "failed".
Respuestas
200 Per-id results. Read failed: a non-empty failed with a 200 is the normal partial-success answer.
400 The body was rejected, or the Idempotency-Key header is missing; details names the field
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The organization is archived, the project is archived, or the idempotency key was already used for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
PUT /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/batch/pause
Pause several tracked queries
Minimum role: manager.
Pauses up to 100 tracked queries of one project, each independently. Always answers 200 when the batch itself was processed: read failed to find out which items were not paused, never the status code. Items are never rolled back because a later one failed. An id that is already paused is reported as successful. Pausing asserts a state, not a transition.
An id that is not a tracked query of this project is reported as failed with tracked_query_not_found, exactly as an id that does not exist at all, and nothing is written for it. Pausing does not cancel a check that is already running. Requires an Idempotency-Key header; a retry must repeat the same ids in the same order to be recognised as a retry rather than refused as a reused key.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
string
Repeating a request with the same key and the same ids answers with the first attempt's result.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
idsObligatorio
string (uuid)[]
Ids of the resources to act on. Duplicates are collapsed.
Respuestas
200 Per-item results. failed is always present, empty list included: read it rather than inferring success from the status.
400 The Idempotency-Key header is missing, the body carried an unknown field, or "ids" was absent, malformed or larger than 100 distinct entries
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The organization or the project is archived, or the idempotency key was already used for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
PUT /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/batch/resume
Resume several tracked queries
Minimum role: manager.
Puts up to 100 paused tracked queries of one project back under the scheduler, each independently. Always answers 200 when the batch itself was processed: read failed to find out which items were not resumed, never the status code. Items are never rolled back because a later one failed.
An id that is already active is reported as successful. Resuming asserts a state, not a transition. An id that is not a tracked query of this project is reported as failed with tracked_query_not_found, exactly as an id that does not exist at all, and nothing is written for it.
No check is run by this operation and nothing is back-filled for the time the queries spent paused. Requires an Idempotency-Key header; a retry must repeat the same ids in the same order to be recognised as a retry rather than refused as a reused key.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
string
Repeating a request with the same key and the same ids answers with the first attempt's result.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
idsObligatorio
string (uuid)[]
Ids of the resources to act on. Duplicates are collapsed.
Respuestas
200 Per-item results. failed is always present, empty list included: read it rather than inferring success from the status.
400 The Idempotency-Key header is missing, the body carried an unknown field, or "ids" was absent, malformed or larger than 100 distinct entries
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The organization or the project is archived, or the idempotency key was already used for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
POST /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/bulk-delete
Delete tracked queries
Minimum role: manager.
Permanently deletes the tracked queries named in ids, at most 100 distinct ids per call. The organization must be active and the project must not be archived. Deletion is hard and cannot be undone: the tracked query is removed along with its captured answers, matches, search pages and rank history, and any check already in flight for it is cancelled.
Those cascades run in the background, so a 200 means the tracked queries were deleted, not that every derived record has finished being purged. Partial success: an id that is not a tracked query of this project, unknown, malformed, already deleted, or belonging to somewhere else, is reported under failed with tracked_query_not_found while the rest are deleted.
It never deletes more than the ids it is given: there is no "delete everything matching a filter" mode. The Idempotency-Key header is required; a retry with the same key and the same body returns this same answer without deleting anything again.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
string
A client-chosen key, unique per operation. Replaying it returns the first answer instead of deleting anything again.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
idsObligatorio
string (uuid)[]
Ids of the resources to act on. Duplicates are collapsed.
Respuestas
200 Per-id results. Read failed: a non-empty failed with a 200 is the normal partial-success answer.
400 The body was rejected, or the Idempotency-Key header is missing; details names the field
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The organization is archived, the project is archived, or the idempotency key was already used for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
PUT /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/bulk/clusters
Add many tracked queries to clusters
Minimum role: manager.
Adds every tracked query named in "ids" to every cluster named in "queryClusterIds". At most 100 distinct tracked queries per call; duplicates in "ids" are collapsed. Partial success: the answer is 200 with a per-item "successful" and "failed" list even when some items failed, nothing is rolled back, and an id that is not a tracked query of this project is reported as a failed item rather than dropped.
Clusters not named are left alone. This adds, it does not replace membership. Every cluster must belong to the project in the path; one that does not is rejected with its field named and nothing is written at all. The "Idempotency-Key" header is required, and a repeat of the same key and body returns the recorded answer without running the batch again.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
string
A client-chosen key, unique per operation, so a lost response can be retried without repeating the batch.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
ids
string (uuid)[]
Tracked queries to add. At most 100 distinct ids; duplicates are collapsed.
queryClusterIds
string (uuid)[]
Clusters every named tracked query is added to. All must belong to the project in the path.
Respuestas
200 Per-item results. Read "failed": a 200 does not mean every item succeeded.
400 The body was rejected: an unknown field, a malformed or missing id, more than 100 distinct ids, a cluster outside this project, or a missing Idempotency-Key
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The organization is archived, the project is archived, or the idempotency key was reused for a different body, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
Removes every tracked query named in "ids" from every cluster named in "queryClusterIds". At most 100 distinct tracked queries per call; duplicates in "ids" are collapsed. Partial success: the answer is 200 with a per-item "successful" and "failed" list even when some items failed, nothing is rolled back, and an id that is not a tracked query of this project is reported as a failed item rather than dropped.
Neither the clusters nor the tracked queries are deleted: only the membership between them. Every cluster must belong to the project in the path; one that does not is rejected with its field named and nothing is written at all. NOTE: this DELETE requires a request body. Some HTTP client libraries and proxies strip bodies from DELETE, and a stripped body is refused with a validation error rather than interpreted as "remove everything".
The "Idempotency-Key" header is required, and a repeat of the same key and body returns the recorded answer without running the batch again.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
string
A client-chosen key, unique per operation, so a lost response can be retried without repeating the batch.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
ids
string (uuid)[]
Tracked queries to remove. At most 100 distinct ids; duplicates are collapsed.
queryClusterIds
string (uuid)[]
Clusters every named tracked query is removed from. All must belong to the project in the path.
Respuestas
200 Per-item results. Read "failed": a 200 does not mean every item succeeded.
400 The body was rejected or missing: an unknown field, a malformed or missing id, more than 100 distinct ids, a cluster outside this project, a stripped DELETE body, or a missing Idempotency-Key
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The organization is archived, the project is archived, or the idempotency key was reused for a different body, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
PUT /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/check
Check several tracked queries now
Minimum role: manager.
Asks for a fresh check of up to 100 named tracked queries straight away, ignoring how recently each was last checked. Answers 200 with per-item results and NO job id: a check that is already in flight for a query is reused rather than started again, so there is no id this operation could hand back that is guaranteed to exist.
Follow progress on the tracked query itself. Its lastCheckedAt advances when the check completes. A successful item means the check was accepted for submission with budget available for it at that moment; it does not mean the check has run. A checked query costs one budget unit per pass (nPasses), and items that do not fit the remaining budget are reported as failed with check_budget_forecast_exhausted, or subscription_not_found when the organization has no entitled subscription. They are never reported as successful.
That budget figure is a forecast for this batch, and a pessimistic one: a tracked query already being checked is joined to the check in flight and costs nothing, but it is still debited here, so an item refused this way may have fitted. Resubmit it in a later batch rather than treating the refusal as a statement about your subscription.
A paused query is reported as failed with tracked_query_already_paused: paused queries are never checked. An id that is not a tracked query of this project is reported as failed with tracked_query_not_found, exactly as an id that does not exist. Requires an Idempotency-Key header; a retry must repeat the same ids in the same order.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
string
Repeating a request with the same key and the same ids answers with the first attempt's result instead of submitting again.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
idsObligatorio
string (uuid)[]
Ids of the resources to act on. Duplicates are collapsed.
Respuestas
200 Per-item results. failed is always present, empty list included: read it rather than inferring success from the status.
400 The Idempotency-Key header is missing, the body carried an unknown field, or "ids" was absent, malformed or larger than 100 distinct entries
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The organization or the project is archived, or the idempotency key was already used for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
PUT /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/check-all
Check every eligible tracked query of a project now
Minimum role: manager.
Submits a fresh check for every eligible tracked query of the project, ignoring how recently each was last checked, least-recently-checked first, and at most 1000 tracked queries per call. Eligible is narrower than active: a paused query is skipped, and so is one whose check is already pending or running for the same engine.
A query whose check is awaiting a retry is included and, WHEN THE ENGINE HAS NOT CHANGED SINCE, costs nothing extra, because its first submission already paid for it; if the engine did change, the pending run is replaced and the replacement is paid for. What is left is trimmed to what the organization's remaining check budget can pay for. A check costs one budget unit per pass.
While a subscription is cancelled but still inside its paid grace window nothing is submitted at all and submitted is 0; name the queries explicitly through the check operation to run them in that window. CALLING AGAIN DOES NOT CONTINUE WHERE THIS CALL STOPPED: submissions are handed to a worker, and a tracked query stops being selected only once that worker has started its check, so a second call made before the queue drains selects and submits the same tracked queries again.
That is safe while the first check is still running, the duplicate is collapsed, and nothing is checked or charged twice, but a check that has already finished is run again and charged again, because this operation ignores staleness by design. To cover a project with more than 1000 eligible tracked queries, wait for the submitted wave to be picked up, each tracked query's lastCheckedAt advances when its check completes, and call again then.
The response lists the tracked queries submitted and carries NO job id: a check already in flight is reused rather than started again, so no id could be guaranteed to exist. Submission is accepted, not completed: a listed tracked query can still lose the last budget units to another caller before the worker reaches it.
The request takes no body, and any field sent is rejected. Requires an Idempotency-Key header.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
string
Repeating a request with the same key answers with the first attempt's result instead of submitting a second wave.
Respuestas
200 The tracked queries submitted for a check
400 The Idempotency-Key header is missing or malformed, or the request carried a body
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The organization or the project is archived, or the idempotency key was already used for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
GET /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/count
Count a project's tracked queries and price checking them
Minimum role: viewer.
Two numbers about one project: how many tracked queries it holds, and what force-checking that same set would cost. Omit status to count every tracked query whatever its status; send active or paused to count and price only those. checkCost is a PRICED DRY RUN expressed in check budget units, one unit per pass, the same unit the plan allowance is counted in, so it is directly comparable with checksAvailable from the entitlements operation, and it is the sum of each matched tracked query's configured passes.
Asking reserves nothing, debits nothing and starts no check. It is deliberately NOT a forecast of what the check-all operation will consume: that operation skips paused queries, skips a query whose check is already pending or running, re-runs a check awaiting retry without charging for it again, and stops at whatever budget is left. None of which is subtracted here.
Count with status=active for the figure closest to a full check-all. Both numbers are read from the write model, so a tracked query created moments ago is already in them; that is why they can be AHEAD of the total returned by the tracked-queries listing, which counts a search projection, and ahead of the keyword listings, which read projections refreshed in the background.
Summing the unfiltered count over every project of an organization, archived projects included, reproduces countOrganizationTrackedQueries, which counts through the same counter in the same store. An archived project still answers, because this is a read, but no check can be submitted there while it stays archived, so its cost is hypothetical.
For a month of scheduled rounds across the whole organization instead of one round over one project, read getOrganizationProjectedMonthlyChecks. No monetary amount is published or implied: the cost of a check is published only in budget units.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
status
query
active | paused
Restrict both numbers to one status. Lower-case; an unknown value is rejected, not ignored. Omitted, every status is counted and priced.
Respuestas
200 The tracked query count and the budget cost of checking that set
400 The status parameter was rejected; the details name the field
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/tracked-queries/count" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Respuesta de ejemplo
{
"count": 42,
"checkCost": 96
}
Analytics
GET /api/v1/metric-glossary
Map everyday wording to a metric and the operation that serves it
Static reference, no project data. Each entry gives a metric, the everyday words people use for it, its unit and range, whether higher or lower is better, the operation that returns it, and example questions. Useful when turning a vague or non-technical request into the right call.
Respuestas
200 The metric catalogue
401 Missing or invalid API key
403 The key lacks the read capability
curl -X GET "https://api.mencoro.com/api/v1/metric-glossary" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/overview
Snapshot rank-health board across an organization active projects
Minimum role: viewer.
One row per active project, share of voice, mention rate, average mention position, positivity index and tracked-query count, ordered by share of voice, plus an organization-level aggregate of the same metrics. Archived projects are excluded. This is a current-state snapshot and takes no date window; for a date-ranged comparison call the per-project operations (getProjectMetrics, getProjectTimeSeries) for each projectId returned here.
Every metric is nullable, and a null means the project has no rank data yet. Not a score of zero. Higher is better for shareOfVoice, mentionRate and positivityIndex; avgMentionPosition is a 1-based rank, so LOWER is better.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
Respuestas
200 Per-project snapshot rows and the organization aggregate
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization the caller can access under this id
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/overview" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/projects/{projectId}/available-filters
Filter values a project is configured for
Minimum role: viewer.
Call this first: it is where every other analytics operation sends you for the valid engines, countries and keyword clusters of a project, and the values it returns are the exact strings the engines, countries and queryClusterIds parameters accept. Anything else is rejected as a 400.
Engines are engine codes, countries are ISO-3166 alpha-2 codes, and clusters are {id, name} objects whose id goes in queryClusterIds. Takes no date window: it describes how the project is configured right now, so a value is listed as soon as a tracked query uses it, even when no response has been captured for it yet.
An empty list therefore means nothing is configured for it, not that no data was collected. Competitor ids are not part of this response.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Respuestas
200 The engines, countries and clusters configured on the project
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/available-filters" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/projects/{projectId}/cited-sources
Domains and pages the AI answers cited
Minimum role: viewer.
The sources the answer engines drew on across a project's AI answers over a date window, ranked by how often they were cited. Per source: citationCount, the total number of citations; distinctResponseCount and distinctQueryCount, how many captured answers and tracked queries it appeared in; avgPosition, its average 1-based rank inside the answers' citation lists, where LOWER is better.
A null avgPosition means no citation in the window carried a position, not a rank of zero; a null domain or sampleTitle means the citation never carried one. total counts the distinct sources matching the window, before paging. The list is UNFILTERED by ownership: the brand's, competitors' and third-party sources sit in the same ranking.
Only the AI answer engines (chatgpt, perplexity, google_ai_overview, google_ai_mode) produce citations, so filtering by google_serp or google_shopping is accepted and returns nothing. Citations still behind an answer engine's redirect (a google.com/goto link, whose URL names the engine rather than the source) are excluded, so a source cited only through such links is absent from this list rather than counted as zero.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
dateFromObligatorio
query
string (date)
Inclusive start of the window, Y-m-d. Must fall inside the data retention window.
Repeatable, or comma-separated. Only the AI engines carry citations.
groupBy
query
domain | pagedefault "domain"
Grain of the roll-up: "domain" by host, "page" by exact URL.
limit
query
integermin 1, max 100, default 20
Page size. A larger value is rejected, never silently reduced.
offset
query
integermin 0, default 0
Number of sources to skip.
Respuestas
200 The cited sources for this page, plus the total number of distinct sources in the window
400 A filter or page bound was rejected; the details name the field
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/cited-sources?dateFrom=2026-01-01&dateTo=2026-01-01" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Respuesta de ejemplo
{
"sources": [],
"total": 0
}
GET /api/v1/organizations/{organizationId}/projects/{projectId}/competitors/co-occurrence
Head-to-head record of the brand against each tracked competitor
Minimum role: viewer.
Restricted to the AI answers where the brand and a competitor are BOTH mentioned, one row per tracked competitor: sharedResponseCount is how many such answers there are, and brandWins / competitorWins / ties split them by who holds the better (lower) best mention position. winRate is the percentage 0-100 of those answers the brand wins; avgOwnPosition and avgCompetitorPosition are the average best mention position each side held, 1-based, so LOWER is better.
exampleQueryText and exampleAiResponseId point at one representative shared answer. Every nullable field means "not known yet" rather than zero: a null winRate or average position is the absence of a shared answer in the window, not a record of losing. Tracked competitors only.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
dateFromObligatorio
query
string (date)
Inclusive start of the window, Y-m-d. Must fall inside the data retention window.
Repeatable, or comma-separated. SERP and Shopping carry no AI answer text, so they contribute no co-occurrence.
countries
query
string[]
ISO-3166 alpha-2 codes or English names. Must be configured on the project.
competitorId
query
string (uuid)
Restricts the answer to a single tracked competitor. Omit it for every tracked competitor. The available-filters endpoint lists the valid ids.
Respuestas
200 One head-to-head row per tracked competitor, under "competitors"
400 A filter was rejected; the details name the field
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/competitors/co-occurrence?dateFrom=2026-01-01&dateTo=2026-01-01" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Respuesta de ejemplo
{
"competitors": []
}
GET /api/v1/organizations/{organizationId}/projects/{projectId}/coverage
Coverage and staleness of a project tracked queries
Minimum role: viewer.
A current-state snapshot answering "what is stale or not being tracked": total is every tracked query on the project, active and paused split it by status, neverChecked counts the active queries that have never run, and overdue counts the active queries whose last check is older than their own check-frequency interval (daily, weekly or monthly).
neverChecked and overdue are disjoint, a query that has never run is never also counted as overdue, and both ignore paused queries, which are not expected to be checked at all. sample lists up to 20 of the overdue queries, most stale first; it is a sample of overdue only, so it never contains a never-checked query and is empty when overdue is 0.
Takes no date window: every count describes the project as it stands right now.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Respuestas
200 Coverage counts and a sample of the most-overdue queries
400 The request was rejected before it reached the project; this endpoint accepts no query parameters, so no filter can be refused here
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/coverage" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/projects/{projectId}/keyword-listings
List a project's keywords with their windowed metrics
Minimum role: viewer.
One row per distinct keyword text of the project. Every tracked query asking that text, on any engine in any country, collapsed into a single row whose variantIds name the tracked queries behind it. Each row carries the metrics of the requested window and a signed trend against the window of equal length immediately before it, where POSITIVE ALWAYS MEANS BETTER whichever direction the metric itself runs.
Positions are 1-based and lower is better; rates, positivityIndex and shareOfVoice are 0-100 and higher is better; mentionPositionStability is a day-to-day spread, so lower is steadier. A null metric means nothing was captured for that keyword in the window. It is not a zero. total counts the KEYWORDS matching the filters, not the rows on this page and not tracked queries; totalVariantCount counts the tracked queries behind the keywords matching every filter EXCEPT search. With a text search applied it still counts the project's variants, so do not size a force-check budget from it on a searched page.
NEITHER IS THE PROJECT'S TRACKED-QUERY COUNT: the count operation reads the write model, while this listing reads projections refreshed in the background from it, so the numbers legitimately differ while those projections catch up. A project whose cached tracked-query count has not been refreshed yet answers an empty page with total 0, the same answer as a project with no tracked queries at all, so treat an unexpected empty page right after creating queries as "not projected yet", not as "no data".
dataDirtySince is non-null while a recalculation is pending, meaning the metrics predate the latest configuration change. Filters narrow which VARIANTS count towards a row, so engines, countries, statuses, checkFrequencies and nPassesValues each report what the filters selected rather than everything the keyword has.
A filter or sort key this endpoint cannot honour is rejected by name, never ignored, and a limit above the maximum is rejected rather than quietly reduced. This operation answers JSON only: a keyword row carries a nested mentionTypeCounts object, so it is not part of the CSV family.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
dateFromObligatorio
query
string (date)
Inclusive start of the window, Y-m-d. Must fall inside the data retention window.
dateToObligatorio
query
string (date)
Inclusive end of the window, Y-m-d. The trend compares against the equally long window ending the day before dateFrom.
Named after the field it orders by. Rows with no value for the chosen key sort last in either direction. An unknown key is rejected, not replaced by the default.
sortOrder
query
asc | descdefault "asc"
limit
query
integermin 1, max 100, default 20
Page size. A larger value is rejected, never silently reduced.
offset
query
integermin 0, default 0
Number of matching keywords to skip before the page starts.
Respuestas
200 A page of keywords, the totals behind it, and whether the metrics are pending recalculation
400 A filter, sort key or page bound was rejected; the details name the field
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/keyword-listings?dateFrom=2026-01-01&dateTo=2026-01-01" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/projects/{projectId}/mentions
Sample of the raw AI mention texts of a project
Minimum role: viewer.
A paginated page of the individual mention texts behind the aggregate numbers, for qualitative review and for checking sentiment labels by eye. Each sample carries the mention text, the engine and country it was seen in, the tracked query that produced it, its sentiment and mention type, and mentionPosition. A 1-based rank inside the answer where LOWER is better, always present.
total counts every mention matching the filters, not the size of the page returned. Only mentions inside the answer text are returned: a citation of the brand URL is not a mention here, and only AI answer engines produce mentions, so restricting engines to google_serp or google_shopping alone returns an empty page rather than an error.
Two fields carry a "not known" rather than a zero: country is null and queryText is empty when the tracked query behind the mention has since been deleted, and competitorId is null when the mention row stores no competitor id. Which is NOT an assertion that the mention is about your own brand, since an untracked competitor also stores none.
Read mentionRelation instead: own and tracked-competitor are what the scraper resolved to a configured entity, untracked-competitor is a rival the project does not track, and null means the row predates the field. brandName carries the mentioned brand, and is the only way to name an untracked competitor, which has no competitor id to resolve one from.
Omitting the competitorId filter returns exactly the rows with no competitor id stored. That is, own-brand AND untracked-competitor mentions together, not every competitor; pass a competitor UUID to restrict the page to that competitor, and use mentionRelation to separate the rest.
For the aggregate positive/neutral/negative split use the sentiment endpoint, and for weighted mention-type counts the mention mix endpoint.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
dateFromObligatorio
query
string (date)
Inclusive start of the window, Y-m-d. Must fall inside the data retention window.
Repeatable, or comma-separated. Non-AI engines contribute no mentions.
countries
query
string[]
ISO-3166 alpha-2 codes or English names. Must be configured on the project.
sentiment
query
positive | neutral | negative
Restrict to one sentiment label. Omit for every sentiment.
mentionType
query
recommendation | comparison | listing | example | reference
Restrict to one mention type. Omit for every type.
competitorId
query
string (uuid)
UUID of a single competitor, as listed by the available-filters endpoint (competitors[].id). Omitted, the page is restricted to mentions storing no competitor id, which is own-brand and untracked-competitor mentions together. See the operation description and read mentionRelation to tell them apart.
recent: newest first. negative: negative sentiment first, then neutral, then positive, newest first inside each. engine and country: grouped alphabetically, newest first inside each group. An unknown value is rejected, not replaced by the default.
limit
query
integermin 1, max 100, default 20
Page size. A larger value is rejected, never silently reduced.
offset
query
integermin 0, default 0
Number of matching mentions to skip before the page starts.
Respuestas
200 A page of mention samples and the total matching the filters
400 A filter was rejected; the details name the field
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/mentions?dateFrom=2026-01-01&dateTo=2026-01-01" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Respuesta de ejemplo
{
"samples": [],
"total": 0
}
GET /api/v1/organizations/{organizationId}/projects/{projectId}/mentions/mix
Composition of a project brand mentions in AI answers
Minimum role: viewer.
Counts of the project brand's own text mentions in AI answers over a date window, grouped three ways: byType (recommendation, comparison, listing, example, reference), byTone (positive, neutral, negative) and byQualifier (direct, conditional. A conditional mention is one the answer hedged with a condition).
These are the inputs behind the Share of Voice weighted score. Every bucket is always present and is a plain count, never null: a zero means no mention of that kind was found in the window. The three groupings count the same mentions, so each one sums to the same total. Only the project brand is counted, never a competitor, and only mentions inside the answer text. A citation of the brand's URL is not a mention here.
Only AI answer engines produce mentions, so restricting engines to google_serp or google_shopping alone returns all zeros. For the positive/neutral/negative split per engine and per competitor use the sentiment endpoint.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
dateFromObligatorio
query
string (date)
Inclusive start of the window, Y-m-d. Must fall inside the data retention window.
Repeatable, or comma-separated. Non-AI engines contribute no mentions.
countries
query
string[]
ISO-3166 alpha-2 codes or English names. Must be configured on the project.
Respuestas
200 Mention counts by type, by tone and by qualifier
400 A filter was rejected; the details name the field
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/mentions/mix?dateFrom=2026-01-01&dateTo=2026-01-01" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Respuesta de ejemplo
{
"byType": {},
"byTone": {},
"byQualifier": {}
}
GET /api/v1/organizations/{organizationId}/projects/{projectId}/metrics
Headline visibility metrics of a project
Minimum role: viewer.
The project overview over a date window: share of voice (own and per competitor), mention / SERP / shopping rates, average and best positions, position stability, the sentiment split and the position-distribution buckets. Positions are 1-based, so a LOWER number is better; rates, the positivity index and share of voice are percentages from 0 to 100, where HIGHER is better.
Every trend* field is the signed change against the immediately preceding window of the same length: negative means an improved position, positive means an improved rate or score. A null metric means "not known yet", never zero: a scalar is null when the window holds no checks at all, and a trend* field is null when there is no earlier window to compare against.
The counters (mentionCount, *TrackedQueryCount, *QueriesWithResult, sentiment* and mentionTypeCounts) are genuine zeros instead, so an empty window reads as zero counts with null rates. dataDirtySince is non-null while a recalculation is pending, meaning the figures may still move for dates from then on.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
dateFromObligatorio
query
string (date)
Inclusive start of the window, Y-m-d. Must fall inside the data retention window.
GET /api/v1/organizations/{organizationId}/projects/{projectId}/metrics/clusters
Rank-tracking metrics per keyword cluster
Minimum role: viewer.
One row per keyword cluster over a date window, with its tracked query and keyword counts, average positions, rates, share of voice and sentiment split. A row whose clusterId is null is the ungrouped bucket: the tracked queries belonging to no cluster. Position metrics are 1-based and LOWER is better; rates, positivityIndex and shareOfVoice are 0-100 percentages where higher is better.
A null metric means nothing was captured for that cluster in the window. It is not a zero, and averaging or charting it as one would misstate the period. dataDirtySince is non-null while a recalculation is pending, meaning the numbers predate the latest configuration change.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
dateFromObligatorio
query
string (date)
Inclusive start of the window, Y-m-d. Must fall inside the data retention window.
ISO-3166 alpha-2 codes or English names. Must be configured on the project.
queryClusterIds
query
string (uuid)[]
Restrict to these clusters. Each must belong to the project.
includeUngroupedQueries
query
booleandefault false
Sent alone, returns only the ungrouped bucket rather than adding it to every cluster.
Respuestas
200 One row per keyword cluster, plus the ungrouped bucket where it applies
400 A filter was rejected; the details name the field
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/metrics/clusters?dateFrom=2026-01-01&dateTo=2026-01-01" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Respuesta de ejemplo
{
"rows": [],
"dataDirtySince": null
}
GET /api/v1/organizations/{organizationId}/projects/{projectId}/metrics/movers
Tracked queries ranked by how much a metric moved
Minimum role: viewer.
One row per tracked query, a single engine plus country, carrying its current metric envelope and the signed change against the immediately preceding window of equal length: a 7-day window is compared with the 7 days before it. Every trend delta is signed so that POSITIVE means improved, including the position trends, where the underlying avgSerpPosition / avgShoppingPosition / avgMentionPosition / avgLinkPosition are 1-based ranks and therefore LOWER is better.
shareOfVoice and positivityIndex are percentages from 0 to 100, where HIGHER is better. Sorting applies to the trend keys only: sortOrder=desc gives the top gainers, asc the top losers. Every nullable field means "not known yet" rather than zero. A null position or shareOfVoice is a query with no data in the window, and a null positivityIndex or trend is a period with no mentions to score, neither of which is a record of losing ground.
total counts the tracked queries the filters match, not the rows on this page. dataDirtySince is a date from which the rank data is being recomputed, or null when nothing is pending; while it is non-null the deltas may still move.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
dateFromObligatorio
query
string (date)
Inclusive start of the window, Y-m-d. Must fall inside the data retention window. The comparison window is the equally long stretch immediately before it.
Which trend delta ranks the rows. Positions improve as they fall, so a positive delta is always an improvement whichever key you pick. An unknown value is rejected, not replaced by the default.
sortOrder
query
asc | descdefault "desc"
desc for the top gainers, asc for the top losers.
limit
query
integermin 1, max 100, default 20
Page size. A value above the maximum is rejected, never clamped.
offset
query
integermin 0, default 0
Respuestas
200 The ranked tracked queries under "rows", with "total" and "dataDirtySince"
400 A filter or page bound was rejected; the details name the field
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/metrics/movers?dateFrom=2026-01-01&dateTo=2026-01-01" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/projects/{projectId}/metrics/share-of-voice-formula
The constants behind the Share of Voice score
Minimum role: viewer.
Static reference data, the same for every project: the weights and multipliers that turn individual brand mentions into a Share of Voice score. Each mention is worth mentionTypeWeights[type] * sentimentMultipliers[tone] * (conditional ? conditionalMultiplier : directMultiplier), and a competitor's Share of Voice is its share of the summed weights of every brand in the window, as a percentage.
mentionTypeWeights is keyed by mention type (recommendation, comparison, listing, example, reference) and sentimentMultipliers by tone (positive, neutral, negative); a negative mention is discounted, not discarded, because it still evidences presence. A conditional mention is one the answer hedged with a condition ("if you need X").
Use this to explain a score, not to recompute one: the counts it applies to come from the mention mix endpoint. Every value is always present and is never null.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Respuestas
200 The Share of Voice weighting constants
400 Not reachable here: the endpoint accepts no query parameters, so it has nothing to reject. Listed because the error envelope is shared across the API
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/metrics/share-of-voice-formula" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/projects/{projectId}/sentiment
Sentiment breakdown of a project brand mentions
Minimum role: viewer.
Positive, neutral and negative split of the brand mentions in AI answers over a date window, per engine and per competitor. A null positivityIndex means no mentions were found in the window, which is not the same as a score of zero.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
dateFromObligatorio
query
string (date)
Inclusive start of the window, Y-m-d. Must fall inside the data retention window.
ISO-3166 alpha-2 codes or English names. Must be configured on the project.
queryClusterIds
query
string (uuid)[]
includeUngroupedQueries
query
booleandefault false
Respuestas
200 Sentiment per engine and per competitor
400 A filter was rejected; the details name the field
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/sentiment?dateFrom=2026-01-01&dateTo=2026-01-01" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Respuesta de ejemplo
{
"perEngine": [],
"perCompetitor": []
}
GET /api/v1/organizations/{organizationId}/projects/{projectId}/timeseries
Rank-tracking metrics of a project over time
Minimum role: viewer.
One point per bucket over the date window, each carrying the brand metrics and one same-shaped entry per requested competitor. Rank metrics (serp, shopping, mention, link) are 1-based averages where LOWER is better; positivity (0-100), shareOfVoice (0-100), mentionRate (0-100) and serpRate (0-100) are scores where higher is better.
Every metric is nullable, and a null means no data was collected for that bucket, which is not the same as a value of zero. A project with no tracked queries returns an empty points list. Prefer weekly or monthly granularity over a long window to keep the response compact.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
dateFromObligatorio
query
string (date)
Inclusive start of the window, Y-m-d. Must fall inside the data retention window.
ISO-3166 alpha-2 codes or English names. Must be configured on the project.
queryClusterIds
query
string (uuid)[]
includeUngroupedQueries
query
booleandefault false
On its own this NARROWS the series to tracked queries that belong to no cluster; combined with queryClusterIds it widens those clusters to also cover them.
competitorIds
query
string (uuid)[]
Repeatable, or comma-separated. Each id adds one series under the competitors map of every point.
Respuestas
200 Points in bucket order, plus dataDirtySince: a date from which the rank data is being recomputed, or null when nothing is pending
400 A filter was rejected; the details name the field
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/timeseries?dateFrom=2026-01-01&dateTo=2026-01-01" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Respuesta de ejemplo
{
"points": [],
"dataDirtySince": null
}
GET /api/v1/organizations/{organizationId}/projects/{projectId}/tracked-queries/{trackedQueryId}/timeseries
Rank-tracking time series of a single tracked query
Minimum role: viewer.
One point per bucket over the date window, each carrying the brand metrics and one same-shaped entry per requested competitor. Positions (serp, shopping, mention, link) are 1-based, so a LOWER number is better; positivity, shareOfVoice, mentionRate and serpRate are percentages from 0 to 100, where higher is better.
Every metric is nullable, and a null means nothing was captured for that entity in that bucket. It is not a zero: a null shareOfVoice means no measurement, a shareOfVoice of 0 means measured and never mentioned. The tracked query fixes its own engine and country, so no engine or country filter is accepted.
A non-null dataDirtySince is a timestamp warning that tracked queries were deleted from the project and historical buckets may still include their contributions until the nightly refresh rebuilds them.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
trackedQueryIdObligatorio
path
string (uuid)
Must belong to the project in the path.
dateFromObligatorio
query
string (date)
Inclusive start of the window, Y-m-d. Must fall inside the data retention window.
dateToObligatorio
query
string (date)
Inclusive end of the window, Y-m-d.
granularity
query
daily | weekly | monthlydefault "daily"
Bucket size. Prefer weekly or monthly for long windows.
competitorIds
query
string (uuid)[]
Competitors to add as extra series, repeatable or comma-separated. Valid ids come from the available-filters endpoint.
Respuestas
200 One point per bucket, with brand and per-competitor metrics
400 A filter was rejected; the details name the field
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization, project or tracked query the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/tracked-queries/$TRACKED_QUERY_ID/timeseries?dateFrom=2026-01-01&dateTo=2026-01-01" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Respuesta de ejemplo
{
"points": [],
"dataDirtySince": null
}
Organizations
GET /api/v1/organizations
List accessible organizations
Returns the organizations the key's owner is an active member of, narrowed to the key's scope. A key scoped to all organizations also sees organizations joined after it was created.
Send Accept: text/csv to receive the same page as a CSV download instead of JSON: same filters, same authorization, same page window and the same maximum of 100 rows. It is this page in another format, not a bulk export, so a whole collection is still read by paging. The CSV carries no total, because a table whose every row is a record has nowhere to put one; read it from the JSON representation of the same request.
Cells beginning with =, +, - or @ are prefixed with an apostrophe so a spreadsheet treats them as text rather than running them as formulas.
Parámetros
Nombre
En
Tipo
Descripción
limit
query
integermin 1, max 100, default 20
offset
query
integermin 0, default 0
search
query
stringmax length 100
status
query
active | archived
sortBy
query
createdAt | namedefault "createdAt"
sortOrder
query
asc | descdefault "desc"
Respuestas
200 Accessible organizations
401 Missing or invalid API key
403 The key lacks the read capability
curl -X GET "https://api.mencoro.com/api/v1/organizations" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Requires a key scoped to all organizations and the "organization:manage" capability: a key limited to named organizations cannot widen its own reach by creating one. Preview it first and send the confirmation in X-Mencoro-Confirmation together with an Idempotency-Key.
Parámetros
Nombre
En
Tipo
Descripción
X-Mencoro-ConfirmationObligatorio
header
string
Idempotency-KeyObligatorio
header
string
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
name
stringmin length 3, max length 100
Respuestas
201 Organization created. Your owner membership follows asynchronously, so a read immediately afterwards can answer 404 until it lands.
401 Missing or invalid API key
403 The key is not scoped to all organizations, or lacks "organization:manage"
409 The confirmation is invalid, expired, already used, or its effects changed
428 No confirmation was sent; preview the operation first
An organization outside the key's scope, or one the caller is not an active member of, answers 404 - the API never confirms that an inaccessible organization exists.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
Respuestas
200 The organization
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization the caller can access under this id
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID" \
-H "Authorization: Bearer $MENCORO_API_KEY"
A partial update: omit a field to leave it alone, send it as null to clear it. Preview it first; the confirmation is bound to the current values, so an edit made by somebody else in between invalidates it rather than being silently overwritten. The organization image is deliberately NOT writable here, although the Mencoro app accepts one in the equivalent call: a published JSON API is the wrong place to carry a 10MB base64 blob in a body that also has to be fingerprinted for idempotency and digested for the confirmation.
The image stays readable as imageUrl; changing it is done in the app.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
X-Mencoro-ConfirmationObligatorio
header
string
Idempotency-KeyObligatorio
header
string
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
name
stringmin length 3, max length 100
description
string
contactEmail
string (email)
Respuestas
200 The updated organization
401 Missing or invalid API key
403 The key lacks the organization:manage capability
404 No organization the caller can access under this id
409 The confirmation is invalid, expired, already used, or the organization changed since the preview
428 No confirmation was sent; preview the operation first
POST /api/v1/organizations/{organizationId}/archive
Archive an organization
Minimum role: owner.
Archiving also archives the active projects of the organization, cancels its pending invitations and cancels its subscription at the end of the current billing period. Those effects are applied by background subscribers, so a 200 means the organization was archived, not that every effect has finished.
Preview it first to see exactly what will be touched.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
X-Mencoro-ConfirmationObligatorio
header
string
The confirmation.token returned by POST /api/v1/organization-operation-previews for this exact action, organization and body. Single use, valid for five minutes, and bound to the effects the preview declared: if the organization gained a project or lost an invitation in between, it is refused with 409 rather than doing more than was agreed. Without it the call answers 428.
Idempotency-KeyObligatorio
header
stringmin length 8, max length 255
Repeat it to retry a lost response. The replay is answered from the record without claiming the confirmation again, so a retry is never refused for presenting a confirmation the first attempt already spent.
Respuestas
200 The organization in its new state
401 Missing or invalid API key
403 The key lacks the organization:manage capability
404 No organization the caller can access under this id
409 The confirmation is invalid, expired, already used, or its declared effects changed; or the status transition is not allowed
428 No confirmation was sent; preview the operation first
GET /api/v1/organizations/{organizationId}/entitlements
Get an organization's plan allowance and consumption
Minimum role: owner.
Returns what the current plan allows, how much of it has been consumed and when the allowance next resets, taken from the most recent subscription contract whether it is running or cancelled. An organization that has never subscribed answers status: "none" with every budget and consumption field null. Null means "no plan on file, so not known", which is deliberately distinct from a budget or a consumption of zero.
Commercial and provider details (prices, Stripe identifiers, internal tier codes) are not part of this contract.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
Respuestas
200 The organization's allowance and consumption
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization the caller owns under this id
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/entitlements" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/membership-stats
Membership, project and invitation counts for an organization
Minimum role: owner.
Pre-computed counts of the organization's members, projects and outstanding invitations, read from a materialized view that is refreshed periodically, computedAt says when the snapshot was taken, so a member added since the last refresh is not counted yet. Every count is always an integer and a zero means zero; an organization whose row has not been computed yet answers 404 with code organization_membership_stats_not_found, never a body of zeros, so "none" and "not known yet" are never confused.
Counts cover the whole organization, active and inactive alike: totalMembersCount includes suspended members, and totalProjectsCount includes archived projects. pendingInvitationsCount counts only invitations that are still pending and not yet expired.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
Respuestas
200 The organization's membership snapshot
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization the caller owns under this id (code organization_not_found), or the snapshot has not been computed for it yet (code organization_membership_stats_not_found)
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/membership-stats" \
-H "Authorization: Bearer $MENCORO_API_KEY"
POST /api/v1/organizations/{organizationId}/restore
Restore an archived organization
Minimum role: owner.
Restoring reinstates the projects that were archived as part of archiving this organization - projects archived on their own stay archived - and aborts a pending subscription cancellation. Invitations cancelled by the archive are not reinstated. Preview it first to see which effects are reversible.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
X-Mencoro-ConfirmationObligatorio
header
string
Idempotency-KeyObligatorio
header
string
Respuestas
200 The organization in its new state
401 Missing or invalid API key
403 The key lacks the organization:manage capability
404 No organization the caller can access under this id
409 The confirmation is invalid, expired, already used, or its declared effects changed; or the status transition is not allowed
428 No confirmation was sent; preview the operation first
Active members, projects (total and active) and pending invitations, in one call. Every value is a count and is always known: 0 means the organization really has none of that thing, and no field is ever null. members.total counts ACTIVE memberships only, so a suspended member is not included; projects.total counts every project including archived ones, and projects.active the non-archived subset.
This is a current-state snapshot and takes no date window.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
Respuestas
200 The organization counts
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization the caller can access under this id
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/stats" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/usage/projected-monthly-checks
Project a month of check consumption from the current tracking configuration
Minimum role: viewer.
What the organization's current configuration would consume in a month, in check budget units, the same unit checkBudget and checksAvailable are counted in by the entitlements operation, so the two are directly comparable when sizing a plan. The arithmetic is published so it can be reproduced rather than trusted: for each ACTIVE tracked query, runs per month (daily 30, weekly 4, monthly 1) multiplied by its nPasses, summed.
A weekly query bills 4, not 4.345: a month is modelled as 30 days and 4 weeks, a planning convention rather than a calendar. Take checkFrequency and nPasses from the tracked-query listing and the arithmetic will match. Though the two sides are read from different places and settle at different times: this figure is computed in the Postgres write model and served from a cache that background subscribers invalidate, while that listing reads an Elasticsearch projection.
Immediately after a write the two can disagree; neither is wrong, they are catching up. PAUSED queries are excluded from both figures; archived PROJECTS are not. Archiving a project does not pause its tracked queries, so they still count here, exactly as they do in countOrganizationTrackedQueries.
activeTrackedQueryCount describes the same population as that count, minus the paused queries. But do not compute the difference to learn how many are paused: THIS OPERATION IS CACHED and that one is read live, so the two can disagree while the cache is invalidated in the background.
This is a projection of the configuration, not a forecast of what will actually be spent: it does not look at the remaining plan budget, does not know which checks will be skipped or retried, and reserves and debits nothing. It is also not the checkCost of countTrackedQueries, which prices one round over one project rather than a month over the organization.
Both values are never null: 0 means nothing is scheduled. This operation takes no query parameters. The population is fixed, and a parameter it cannot honour is rejected with 400 rather than silently ignored.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
Respuestas
200 The projected monthly checks and the active tracked queries behind them
400 A query parameter was sent to an operation that accepts none; the details name it
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization the caller can access under this id
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/usage/projected-monthly-checks" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/usage/tracked-queries
Count the tracked queries an organization has configured
Minimum role: viewer.
How many tracked queries the organization has configured, counted live in PostgreSQL, the write model, over EVERY project it owns, archived projects included, and over every tracked query in them, active and paused alike. It is deliberately a DIFFERENT number from aggregate.totalTrackedQueries in getOrganizationOverview: that one sums a per-project copy held in the Elasticsearch read model and covers ACTIVE projects only, so it excludes archived projects and can lag behind a change that already shows here.
Expect the two to disagree and do not treat either as wrong. This figure does reconcile exactly with countTrackedQueries, which counts one project through the same counter in the same store: sum its unfiltered count over every project, archived included, and you get this number.
For the ACTIVE subset and what it will consume, call getOrganizationProjectedMonthlyChecks, which ranges over the same projects. Do NOT derive the paused count by subtracting one from the other: this number is read live from Postgres while that one is served from a cache invalidated by background subscribers, so the two can disagree while that invalidation catches up and the difference is then a count of nothing.
For how many projects this ranges over, read projects.total and projects.active from getOrganizationStats. The value is never null: 0 means none are configured. This operation takes no query parameters. The population is fixed, and a parameter it cannot honour is rejected with 400 rather than silently ignored.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
Respuestas
200 The organization's tracked-query count
400 A query parameter was sent to an operation that accepts none; the details name it
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization the caller can access under this id
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/usage/tracked-queries" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Respuesta de ejemplo
{
"trackedQueryCount": 124
}
Billing
GET /api/v1/organizations/{organizationId}/subscription
Get the subscription of an organization
Minimum role: viewer.
The most recent subscription contract of the organization, whatever its state: tier, billing interval, check budget and consumption, and the cancellation and grace dates. An organization that has never subscribed answers 200 with "status": "none" and every other field null - a null is "not applicable", never a stand-in for a zero budget or zero consumption.
Stripe identifiers, prices and payment methods are not part of this API.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
Respuestas
200 The subscription contract, or the "none" state
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization the caller can access under this id
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/subscription" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/projects/{projectId}/ai-responses
List captured AI answers
Minimum role: viewer.
Every AI answer captured for a project, newest first, one page at a time. This is the evidence under the analytics operations: the full answer text and the sources the engine cited, exactly as captured. Read unresolved on a citation before attributing its domain. A true value means the URL is still a redirector and the domain belongs to that redirector, not to the publisher; count the citation, do not credit the site.
passIndex and passCount describe multi-pass sampling: rows sharing a trackedQueryId and capturedAt are passes of one run, not duplicates, so aggregating across them without dividing by passCount double-counts that run. responseText is the whole answer, so a page of 100 is a large response. Lower limit rather than paging blind.
Captures are kept for 16 months and purged after that; a dateFrom before the window is rejected rather than answered with an empty page. total counts every capture the filter matches, not the size of this page.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
dateFrom
query
string (date)
Inclusive lower bound, widened to 00:00:00 UTC of the named day. Must be inside the retention window.
dateTo
query
string (date)
Inclusive upper bound, widened to 23:59:59 UTC of the named day.
trackedQueryId
query
string (uuid)
Only captures of this tracked query. Must belong to the project in the path.
GET /api/v1/organizations/{organizationId}/projects/{projectId}/search-snapshots
List captured search-results pages
Minimum role: viewer.
Every organic search page captured for a project, newest first, one page at a time. This is what the rank figures in the analytics operations were computed from: the ranked results as they stood at capturedAt, not as they stand now. Read unresolved on a result before attributing its domain. A true value means the URL is still a redirector and the domain belongs to that redirector; count the result, do not credit the site.
rating and ratingVotes come from a rich-result star rating when Google showed one and are absent far more often than present; their absence says nothing about the page. There is no engines filter because every capture here comes from Google SERP. Captures are kept for 16 months and purged after that; a dateFrom before the window is rejected rather than answered with an empty page.
total counts every capture the filter matches, not the size of this page.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
dateFrom
query
string (date)
Inclusive lower bound, widened to 00:00:00 UTC of the named day. Must be inside the retention window.
dateTo
query
string (date)
Inclusive upper bound, widened to 23:59:59 UTC of the named day.
trackedQueryId
query
string (uuid)
Only captures of this tracked query. Must belong to the project in the path.
limit
query
integermin 1, max 100, default 20
Page size. A larger value is rejected, never silently reduced.
offset
query
integermin 0, default 0
Number of captures to skip before the page starts.
sortOrder
query
asc | descdefault "desc"
Direction of the capture-time ordering. An unknown value is rejected, not replaced by the default.
Respuestas
200 A page of captured search-results pages and the total the filter matches
400 A filter, pagination or ordering parameter was rejected; the details name the field
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/search-snapshots" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/projects/{projectId}/shopping-snapshots
List captured shopping-results pages
Minimum role: viewer.
Every shopping page captured for a project, newest first, one page at a time: the ranked offers as they stood at capturedAt. price and currency are what the seller showed at that moment, no tax normalisation, no shipping, no conversion, and two offers in one snapshot may carry different currencies, so convert before comparing.
productId is the marketplace's own identifier for the listing, stable enough to follow one offer across snapshots, and it is not a Mencoro id. Offers turn over far faster than organic results, so two snapshots days apart routinely share none; that is the marketplace behaving normally, not a gap in the capture.
Unlike organic results, a shopping offer carries no unresolved flag: the capture pipeline does not record one for this surface. Shopping captures are trimmed by the same raw-data purge as AI answers and search pages, so the same retention floor applies: a dateFrom before it is refused rather than answered with an empty page.
total counts every capture the filter matches, not the size of this page.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
dateFrom
query
string (date)
Inclusive lower bound, widened to 00:00:00 UTC of the named day. A date before the retention floor is refused rather than answered with an empty page: shopping captures are aged out by the raw-data purge like every other capture.
dateTo
query
string (date)
Inclusive upper bound, widened to 23:59:59 UTC of the named day.
trackedQueryId
query
string (uuid)
Only captures of this tracked query. Must belong to the project in the path.
limit
query
integermin 1, max 100, default 20
Page size. A larger value is rejected, never silently reduced.
offset
query
integermin 0, default 0
Number of captures to skip before the page starts.
sortOrder
query
asc | descdefault "desc"
Direction of the capture-time ordering. An unknown value is rejected, not replaced by the default.
Respuestas
200 A page of captured shopping-results pages and the total the filter matches
400 A filter, pagination or ordering parameter was rejected; the details name the field
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/shopping-snapshots" \
-H "Authorization: Bearer $MENCORO_API_KEY"
POST /api/v1/organizations/{organizationId}/projects/{projectId}/clusters
Create a keyword cluster
Minimum role: manager.
Creates one empty keyword cluster in the project. The name is trimmed and lower-cased before it is stored, and it must be unique within the project: a name that already exists is refused with 409 and nothing is merged into the existing cluster. The cluster starts with no tracked queries in it. This operation does not assign anything to it.
The organization must not be archived; an archived project IS refused with 409, stricter than the Mencoro app, which lets cluster writes into one. Requires the write capability and an Idempotency-Key header.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
stringmin length 8, max length 255
A token you choose per operation, 8 to 255 printable ASCII characters with no spaces; a UUID is the obvious choice. Repeat it to retry a lost response without creating a second cluster. The key is scoped to your API key, and it is bound to the method, the path and the body of the first attempt: repeating it with anything else changed is refused with 409 rather than replayed.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
name
stringmax length 200
Stored trimmed and lower-cased. Unique within the project.
Respuestas
201 The cluster that was created
400 The body was rejected, or the Idempotency-Key header is missing; the details name the field
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 A cluster with this name already exists in the project, the organization is archived, the project is archived, or the idempotency key was reused for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
GET /api/v1/organizations/{organizationId}/projects/{projectId}/clusters/{clusterId}
Get one of a project's keyword clusters
Minimum role: viewer.
Returns a single keyword cluster of the project, the same projection the cluster listing returns for each of its rows. A cluster belonging to another project answers 404, the same answer an unknown id and a malformed one get, so the API never confirms that a cluster the caller cannot reach exists.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Must belong to the organization in the path.
clusterIdObligatorio
path
string (uuid)
Must be a cluster of the project in the path.
Respuestas
200 The keyword cluster
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization, project or cluster the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/clusters/$CLUSTER_ID" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Changes the name of one keyword cluster and nothing else: the tracked queries assigned to it are untouched, and its id does not change, so nothing a client stored breaks. The new name is trimmed and lower-cased and must be unique within the project; a collision is refused with 409.
Renaming to the name the cluster already has is accepted and is a no-op. The organization must not be archived; an archived project IS refused with 409, stricter than the Mencoro app, which lets cluster writes into one. Requires the write capability and an Idempotency-Key header.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
clusterIdObligatorio
path
string (uuid)
Must be a cluster of the project in the path.
Idempotency-KeyObligatorio
header
string
Repeat it to retry a lost response without renaming twice.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
name
stringmax length 200
Stored trimmed and lower-cased. Unique within the project.
Respuestas
200 The cluster in its new state
400 The body was rejected, or the Idempotency-Key header is missing; the details name the field
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization, project or cluster the caller can access under these ids
409 Another cluster in the project already has this name, the organization is archived, the project is archived, or the idempotency key was reused for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
Deletes one keyword cluster. The tracked queries that were in it are NOT deleted: they are unassigned from this cluster and keep every other cluster they belong to. Analytics filtered by this cluster id return nothing afterwards, including for dates before the deletion, because that filter reads current membership.
This cannot be undone. Recreating a cluster with the same name produces a new id and an empty cluster. The organization must not be archived, and neither must the project: an archived project IS refused with 409, stricter than the Mencoro app, which lets cluster writes into one.
Requires the write capability and an Idempotency-Key header.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
clusterIdObligatorio
path
string (uuid)
Must be a cluster of the project in the path.
Idempotency-KeyObligatorio
header
string
Repeat it to retry a lost response; a fresh key answers 404 once the cluster is gone.
Respuestas
200 The cluster was deleted
400 A body was sent, or the Idempotency-Key header is missing; the details name the field
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization, project or cluster the caller can access under these ids
409 The organization is archived, or the idempotency key was reused for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
POST /api/v1/organizations/{organizationId}/projects/{projectId}/clusters/batch
Create several keyword clusters at once
Minimum role: manager.
Creates up to 100 empty keyword clusters in one call. Names are trimmed and lower-cased and repeated names in the body are collapsed before anything is written. Partial success: the answer is always 200 and reports every name under successful or under failed. A name already taken in the project fails with query_cluster_name_already_exists and is NOT resolved to the existing cluster, while the other names are still created.
Nothing is rolled back because one name failed. The clusters are created empty; no tracked query is assigned to them. The organization must not be archived; an archived project IS refused with 409, stricter than the Mencoro app, which lets cluster writes into one. Requires the write capability and an Idempotency-Key header.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
string
Repeat it to retry a lost response without creating the batch twice.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
namesObligatorio
string[]
Cluster names to create, already trimmed and lower-cased on the server. Duplicates are collapsed.
Respuestas
200 Per-name results; read failed rather than inferring success from the status
400 The body was rejected, or the Idempotency-Key header is missing; the details name the field
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The organization is archived, or the idempotency key was reused for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
POST /api/v1/organizations/{organizationId}/projects/{projectId}/clusters/jobs
Start a keyword clustering job
Minimum role: manager.
Asks the clustering service to propose keyword clusters for up to 500 tracked queries of the project, and answers 202 with the job to poll. The work runs in the background and a 202 says it was accepted, never that it succeeded. THE JOB WRITES NOTHING: it produces a proposal, and nothing changes until it is applied through the apply operation, which is a separate call.
Duplicate query texts within the selection are sent once. Requires an entitled subscription (402 otherwise) and the organization must be active and the project not archived. Rate limited to 10 starts per minute per organization, shared with the same operation in the web application.
Requires the write capability and an Idempotency-Key header; repeating the key returns the first job rather than starting a second.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
string
Repeat it to retry a lost response without starting a second job.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
trackedQueryIdsObligatorio
string (uuid)[]
The tracked queries to cluster. Duplicates are collapsed.
modeObligatorio
fill_gaps | full_regroup | add_on_top
fill_gaps groups only tracked queries that belong to no cluster; add_on_top adds the new clusters to whatever each query already has; full_regroup replaces the current clusters with the job's.
restrictToExistingClusters
booleandefault false
When true the job may only use clusters the project already has, and leaves a query ungrouped rather than inventing a name for it.
Respuestas
202 The job was accepted; poll trackingUrl until its status is terminal
400 The body was rejected, or the Idempotency-Key header is missing; the details name the field
401 Missing or invalid API key
402 The organization has no entitled subscription
403 The key lacks the write capability
404 No organization, project or tracked query the caller can access under these ids
409 The organization is archived, the project is archived, there is nothing to cluster, or the idempotency key was reused for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
429 More than 10 clustering starts in a minute for this organization; Retry-After says when to try again
POST /api/v1/organizations/{organizationId}/projects/{projectId}/clusters/jobs/{jobId}/apply
Apply the result of a clustering job
Minimum role: manager.
Writes a completed clustering job onto the tracked queries it was computed for: it creates the clusters the job proposed that the project does not have yet, then assigns each tracked query according to the merge mode the job was started with, fill_gaps leaves already grouped queries alone, add_on_top only adds, full_regroup replaces a query's clusters with the proposed set and therefore REMOVES clusters that are not in it, but only for a tracked query the job actually returned an assignment for.
A tracked query the job was started over and produced no assignment for is listed under unassigned and left exactly as it was, under every mode; it is not treated as "belongs to no cluster" and is never stripped. That matters most with restrictToExistingClusters, where the model is expected to return nothing for queries that fit no existing cluster.
The body must be empty: the assignments, the target tracked queries and the mode all come from the job, so this call cannot apply something the job did not produce. Synchronous and partially successful. Always 200, with each tracked query under successful or failed, and nothing rolled back because one failed.
A job that is not completed, or one that produced no assignments, is refused with 409. Requires the write capability and an Idempotency-Key header; repeating the key returns the first answer rather than applying twice.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
jobIdObligatorio
path
string (uuid)
Must be a clustering job started for this organization and project.
Idempotency-KeyObligatorio
header
string
Repeat it to retry a lost response without applying the job twice.
Respuestas
200 What was written; read failed rather than inferring success from the status
400 A body was sent, or the Idempotency-Key header is missing; the details name the field
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization, project or clustering job the caller can access under these ids
409 The job is not completed, produced nothing that can be applied, the organization is archived, the project is archived, or the idempotency key was reused for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
GET /api/v1/organizations/{organizationId}/projects
List an organization's projects
Minimum role: viewer.
Metrics come from the same read model the application uses, so the figures match what the product shows. A null metric means "not known yet", never zero.
Send Accept: text/csv to receive the same page as a CSV download instead of JSON: same filters, same authorization, same page window and the same maximum of 100 rows. It is this page in another format, not a bulk export, so a whole collection is still read by paging. The CSV carries no total, because a table whose every row is a record has nowhere to put one; read it from the JSON representation of the same request.
A list-valued field is joined into one cell with ; as a display projection. Parse the JSON if you need the structure. Cells beginning with =, +, - or @ are prefixed with an apostrophe so a spreadsheet treats them as text rather than running them as formulas.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
limit
query
integermin 1, max 100, default 20
Page size. A larger value is rejected, never silently reduced.
offset
query
integermin 0, default 0
Rows to skip before the page starts. Page by advancing it in steps of limit until it reaches total.
POST /api/v1/organizations/{organizationId}/projects
Create a project and the brand monitoring profile its checks run against
Minimum role: manager, in an active organization.
Requires the "write" capability. Creates the project, the brand monitoring profile holding the domains and brand names to watch, and one competitor per entry of competitors, in a single call. The project id is minted by the server; a caller-supplied id is rejected as an unknown field.
What is NOT done: no tracked queries are created, no check is run and no scraping is scheduled. A new project has nothing collected against it until tracked queries are added. Each website entry may be a full URL or a bare domain: a URL is reduced to its host with any leading "www." removed, so "https://www.acme.com/pricing" is stored as "acme.com".
Duplicate domains and duplicate brand names are collapsed, exactly as the stored value objects do. Send an Idempotency-Key: a retry with the same key and the same body returns this same project instead of creating a second one.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
stringmin length 8, max length 255
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
nameObligatorio
stringmin length 1, max length 255
websiteDomainsObligatorio
string[]
At least one website URL or domain to monitor.
brandNamesObligatorio
string[]
At least one brand name to match in AI answers and search results.
competitors
object[]
Competitors to create with the project. Optional; they can also be added later through the competitor endpoints.
Respuestas
201 The created project and its brand monitoring configuration
400 The body or the Idempotency-Key was rejected; details names every field at fault
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization the caller can access under this id
409 The organization is archived, the idempotency key was already used for a different request, or a previous attempt with it ended without a known outcome
GET /api/v1/organizations/{organizationId}/projects/{projectId}
Get a project and its brand monitoring configuration
Minimum role: viewer.
Returns the project together with the domains and brand names it is monitored for and the competitors it is measured against. A project that exists but belongs to another organization answers 404, never 403. A project that has been created but not yet configured for brand monitoring reports empty websiteDomains, brandNames and competitors.
Headline metrics are not part of this response: use listProjects for the per-project figures, or getProjectMetrics for a window.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Respuestas
200 The project and its brand monitoring configuration
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization the caller can access under this id, or no project with this id inside it
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Requires the "write" capability. name is the only writable field and it is required. What is NOT done: the monitored domains and brand names are not touched (use updateProjectBrandProfile) and competitors are not touched, added or removed (use the competitor endpoints). Sending websiteDomains, brandNames or competitors here is refused with the field named, never applied in part and never ignored.
Renaming a project changes nothing about the data already collected against it. A project that belongs to another organization answers 404, never 403. An archived project answers 409: restore it first. Unless the call is a retry carrying the key of a rename that already succeeded, which is answered from the record whatever the project's state is now.
Send an Idempotency-Key; a retry with the same key and body returns the recorded answer.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
stringmin length 8, max length 255
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
nameObligatorio
stringmin length 1, max length 255
Respuestas
200 The project in its new state
400 The body or the Idempotency-Key was rejected; details names every field at fault
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The project is archived, the organization is archived, the idempotency key was already used for a different request, or a previous attempt with it ended without a known outcome
POST /api/v1/organizations/{organizationId}/projects/{projectId}/archive
Archive a project
Minimum role: manager, in an active organization.
Requires the "write" capability. Archiving stops a project from being modified: its name, brand profile and competitors are refused with 409 until it is restored. What is NOT done: nothing is deleted. Tracked queries, captured responses, mentions and every metric already collected stay exactly as they are, and restoreProject brings the project back with all of it.
Archiving is recorded as done by the caller, not by an organization cascade, so restoring the organization later will not restore this project. Restore it explicitly. This endpoint takes no body, and one carrying fields is refused. Archiving an already archived project answers 409, unless the call is a retry carrying the key that archived it.
Send an Idempotency-Key; a retry with the same key returns the recorded answer.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
stringmin length 8, max length 255
Respuestas
200 The project in its new state
400 A body was sent, or the Idempotency-Key was rejected
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The project is already archived, the organization is archived, the idempotency key was already used for a different request, or a previous attempt with it ended without a known outcome
GET /api/v1/organizations/{organizationId}/projects/{projectId}/brand-profile
Get a project's brand monitoring profile
Minimum role: viewer.
The brand identity every check of this project is matched against: the tracked brand terms, the website domains, and the generated description of what the brand does. A null description means it has not been generated yet, the generator runs asynchronously after the names or domains change, which is not the same as an empty one.
An empty brandNames or websiteDomains array means the profile exists and names nothing; a project whose profile has not been created at all answers 404.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Must belong to the organization in the path.
Respuestas
200 The project's brand monitoring profile
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids, or the project has no brand profile
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/brand-profile" \
-H "Authorization: Bearer $MENCORO_API_KEY"
PUT /api/v1/organizations/{organizationId}/projects/{projectId}/brand-profile
Replace a project's brand monitoring profile
Minimum role: manager, on an active organization and a project that is not archived.
Replaces the brand terms and website domains every check of this project is matched against: the lists sent become the lists stored, so a term left out is removed. Both lists are required and neither may be empty. A project must keep at least one brand name and one domain to match anything.
A domain may be sent as a full URL or as a bare host; a URL is reduced to its host and a leading "www." is dropped, which is the form the profile is read back in. Duplicates, including two URLs that reduce to the same host, are collapsed. This operation does NOT touch the project name or its competitors, which are separate resources, and it does not regenerate the brand description: that runs asynchronously afterwards, so the description in the response is the one stored at the time of the write.
An Idempotency-Key header is required.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Must belong to the organization in the path.
Idempotency-KeyObligatorio
header
string
Unique per attempt. A retry carrying the same key and the same body is answered from the record instead of running again.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
websiteDomains
string[]
Domains a cited link or a search result is matched against. A full URL or a bare host.
brandNames
string[]
Terms a mention in an AI answer is matched against.
Respuestas
200 The profile as stored
400 The body failed validation, or the Idempotency-Key header is missing
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids, or the project has no brand profile
409 The organization is archived, the project is archived, or the idempotency key was reused for a different body, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
GET /api/v1/organizations/{organizationId}/projects/{projectId}/clusters
List the keyword clusters of a project
Minimum role: viewer.
The keyword clusters configured on a project, one page at a time. Each cluster id is exactly what the analytics operations accept in their queryClusterIds filter. Pass the id, never the name. Names are unique within a project and are stored lower-cased, so the listing is ordered by name with no ties and paging over it neither repeats nor skips a cluster.
total counts every cluster in the project, not the size of the page returned. A cluster carries no metrics of its own and no membership count: for the tracked queries inside a cluster, filter the tracked-query operations by its id. An empty list means the project has no clusters configured, which is not an error and is not a statement about whether any data has been collected.
Send Accept: text/csv to receive the same page as a CSV download instead of JSON: same filters, same authorization, same page window and the same maximum of 100 rows. It is this page in another format, not a bulk export, so a whole collection is still read by paging. The CSV carries no total, because a table whose every row is a record has nowhere to put one; read it from the JSON representation of the same request.
A list-valued field is joined into one cell with ; as a display projection. Parse the JSON if you need the structure. Cells beginning with =, +, - or @ are prefixed with an apostrophe so a spreadsheet treats them as text rather than running them as formulas.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
limit
query
integermin 1, max 100, default 20
Page size. A larger value is rejected, never silently reduced.
offset
query
integermin 0, default 0
Number of clusters to skip before the page starts.
sortOrder
query
asc | descdefault "asc"
Direction of the name ordering. An unknown value is rejected, not replaced by the default.
Respuestas
200 A page of the project's keyword clusters and the total in the project
400 A pagination or ordering parameter was rejected; the details name the field
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/clusters" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/projects/{projectId}/competitors
List the competitors tracked by a project
Minimum role: viewer.
The competitors configured on the project, one page at a time, with the website domains and brand names each one is matched against. total counts every competitor of the project, not the size of this page, so a project with more than limit competitors needs offset to read them all.
Ordering is by id, which for a UUID v7 is roughly creation order, and sortOrder chooses its direction; there is no other sort key and no text search, and sending sortBy or search is rejected rather than ignored. A project whose brand monitoring profile has not been created yet answers 200 with an empty collection, which means "nothing configured yet" rather than "no competitors found".
Internal fields the pipeline writes, the auto-generated brand description used by the mention classifier, and the internal brand monitoring profile id, are not part of this contract.
Send Accept: text/csv to receive the same page as a CSV download instead of JSON: same filters, same authorization, same page window and the same maximum of 100 rows. It is this page in another format, not a bulk export, so a whole collection is still read by paging. The CSV carries no total, because a table whose every row is a record has nowhere to put one; read it from the JSON representation of the same request.
A list-valued field is joined into one cell with ; as a display projection. Parse the JSON if you need the structure. Cells beginning with =, +, - or @ are prefixed with an apostrophe so a spreadsheet treats them as text rather than running them as formulas.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
limit
query
integermin 1, max 100, default 20
Page size. A larger value is rejected, never silently reduced.
offset
query
integermin 0, default 0
Number of competitors to skip before the page starts.
sortOrder
query
asc | descdefault "asc"
Direction of the id ordering. An unknown value is rejected, not replaced by the default.
Respuestas
200 The project's competitors
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or project the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/competitors" \
-H "Authorization: Bearer $MENCORO_API_KEY"
POST /api/v1/organizations/{organizationId}/projects/{projectId}/competitors
Add a competitor to a project
Minimum role: manager, on an active organization and a project that is not archived.
Creates one competitor with the domains and brand names its mentions are matched against. Both lists are required and neither may be empty: a competitor that matches on nothing would never be found in an answer. A domain may be sent as a full URL or as a bare host; a URL is reduced to its host and a leading "www." is dropped.
Duplicates are collapsed. The id is assigned by the server and cannot be chosen, and neither the auto-generated brand description nor the internal brand monitoring profile id can be set. Sending either is refused as an unknown field. Adding a competitor does NOT re-match the answers already captured: it applies to checks from here on.
A project whose brand monitoring profile has not been created yet answers 404. An Idempotency-Key header is required.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Must belong to the organization in the path.
Idempotency-KeyObligatorio
header
string
Unique per attempt. Without it a lost response cannot be retried without risking a second competitor.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
name
stringmax length 200
The competitor's display name
websiteDomains
string[]
Domains a result is matched against for this competitor. A full URL or a bare host.
brandNames
string[]
Names a mention is matched against for this competitor
Respuestas
201 The competitor as stored
400 The body failed validation, or the Idempotency-Key header is missing
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids, or the project has no brand monitoring profile
409 The organization is archived, the project is archived, or the idempotency key was reused for a different body, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
GET /api/v1/organizations/{organizationId}/projects/{projectId}/competitors/{competitorId}
Get one of a project's competitors
Minimum role: viewer.
Returns a single competitor of the project, the same projection the competitor listing returns for each of its rows. A competitor belonging to another project answers 404, the same answer an unknown id and a malformed one get, so the API never confirms that a competitor the caller cannot reach exists.
A project whose brand monitoring profile has not been created yet has no competitors at all and answers 404 for any competitor id.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Must belong to the organization in the path.
competitorIdObligatorio
path
string (uuid)
Must belong to the project in the path.
Respuestas
200 The competitor
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization, project or competitor the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/competitors/$COMPETITOR_ID" \
-H "Authorization: Bearer $MENCORO_API_KEY"
PUT /api/v1/organizations/{organizationId}/projects/{projectId}/competitors/{competitorId}
Replace a competitor
Minimum role: manager, on an active organization and a project that is not archived.
Replaces the competitor's name, domains and brand names: the lists sent become the lists stored, so a term left out is removed. Both lists are required and neither may be empty. A competitor that matches on nothing would never be found in an answer. A domain may be sent as a full URL or as a bare host; a URL is reduced to its host and a leading "www." is dropped.
Duplicates are collapsed. The auto-generated brand description cannot be set, and sending it is refused as an unknown field. Changing the matching rules does NOT re-match the answers already captured: it applies to checks from here on. A competitor belonging to another project answers 404, the same answer an unknown id gets.
An Idempotency-Key header is required.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Must belong to the organization in the path.
competitorIdObligatorio
path
string (uuid)
Must belong to the project in the path.
Idempotency-KeyObligatorio
header
string
Unique per attempt. A retry carrying the same key and the same body is answered from the record instead of running again.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
name
stringmax length 200
The competitor's display name
websiteDomains
string[]
Domains a result is matched against for this competitor. A full URL or a bare host.
brandNames
string[]
Names a mention is matched against for this competitor
Respuestas
200 The competitor as stored
400 The body failed validation, or the Idempotency-Key header is missing
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization, project or competitor the caller can access under these ids
409 The organization is archived, the project is archived, or the idempotency key was reused for a different body, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
Minimum role: manager, on an active organization and a project that is not archived.
Removes the competitor and, asynchronously, every stored mention, search result and shopping result attributed to it, in AI answers and search captures already taken. This is permanent and it changes historical analytics: share of voice and competitor co-occurrence recomputed after the cascade will not include it.
A 200 means the competitor is gone; the cascade runs on the event bus and finishes shortly afterwards. The response body is the competitor as it was immediately before removal, because it can no longer be read back. The request takes no body, and sending one is refused. A competitor belonging to another project answers 404, the same answer an unknown id gets.
An Idempotency-Key header is required.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Must belong to the organization in the path.
competitorIdObligatorio
path
string (uuid)
Must belong to the project in the path.
Idempotency-KeyObligatorio
header
string
Unique per attempt. A retry carrying the same key is answered from the record instead of running again.
Respuestas
200 The competitor as it was immediately before removal
400 A body was sent, or the Idempotency-Key header is missing
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization, project or competitor the caller can access under these ids
409 The organization is archived, the project is archived, or the idempotency key was reused for a different request, a concurrent request with the same key is still running, or a previous attempt with it ended without a known outcome
POST /api/v1/organizations/{organizationId}/projects/{projectId}/restore
Restore an archived project
Minimum role: manager, in an active organization.
Requires the "write" capability. Brings an archived project back to active, with every tracked query, capture and metric it had when it was archived. What is NOT done: no check is run and no scraping is scheduled as a result. Collection resumes on the project's own schedule. Restoring clears the record of who archived the project, so a project restored here is treated as an ordinary active project by any later organization archive.
A project archived because its organization was archived cannot be restored on its own: restore the organization, which restores them all. Restoring a project that is already active answers 409, unless the call is a retry carrying the key that restored it. This endpoint takes no body, and one carrying fields is refused.
Send an Idempotency-Key; a retry with the same key returns the recorded answer.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
stringmin length 8, max length 255
Respuestas
200 The project in its new state
400 A body was sent, or the Idempotency-Key was rejected
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The project is not archived, the organization is archived, the idempotency key was already used for a different request, or a previous attempt with it ended without a known outcome
POST /api/v1/organizations/{organizationId}/brand-name-suggestions
Start a brand-name alias suggestion job
Minimum role: manager.
Starts a background, web-search-grounded job that suggests alias spellings for one entity - a brand, a project or a competitor - described entirely by the body, and answers 202 with the job to poll; it never returns suggestions inline. The entity need not exist: nothing is looked up, nothing is attached and nothing is saved, so the suggestions are the caller's to apply.
Names sent in enteredBrandNames are excluded from the result. The organization must be active; no subscription is required, matching the application behaviour this mirrors. Ten starts per minute per organization, counted across every key of every member; a retry carrying an Idempotency-Key already answered is served from the record and does not count.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
Idempotency-KeyObligatorio
header
string
Repeat it to retry a start whose response was lost; the same key returns the same job instead of starting a second one.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
nameObligatorio
stringmax length 255
The display name of the entity to find aliases for.
websiteDomainsObligatorio
string[]
The entity website domains. At least one is required: the web search is grounded on them, and without one the name alone is ambiguous. Duplicates are collapsed, after the entry count has been checked against maxItems.
enteredBrandNames
string[]
Names already known, excluded from the suggestions. Duplicates are collapsed, after the entry count has been checked against maxItems.
country
stringmin length 2, max length 2
ISO 3166-1 alpha-2 country used to localize the web search.
Respuestas
202 The suggestion job was accepted
400 The body is not a JSON object, names an unknown field, or fails validation; or the Idempotency-Key header is missing
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization the caller can access under this id
409 The organization is archived, or the Idempotency-Key was already used for a different request, or a previous attempt with it ended without a known outcome
429 The organization exceeded ten suggestion starts per minute, or the key exceeded its request budget
POST /api/v1/organizations/{organizationId}/projects/{projectId}/discovery/brands
Start a brand discovery job for a project
Minimum role: manager.
Starts background discovery of the brands and competitors around a project and answers 202 with the job to poll; it never returns brands inline. The job PROPOSES names: it creates and updates nothing, so neither the brand profile nor the competitor list changes because this endpoint was called.
The organization must be active. Unlike keyword and prompt discovery this operation does not require an entitled subscription, matching the application behaviour it mirrors. Ten starts per minute per organization, counted across every key of every member and shared with the same operation in the Mencoro app; a retry carrying an Idempotency-Key already answered is served from the record and does not count.
A project whose brand monitoring profile has not been created yet is still accepted and still billed: the job runs grounded on the project name alone, with no website domains, brand names or competitors to work from, and completes normally. Configure the brand profile first if you want the discovery grounded.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Must belong to the organization in the path.
Idempotency-KeyObligatorio
header
string
Repeat it to retry a start whose response was lost; the same key returns the same job instead of starting a second one.
Cuerpo de la petición
application/json, Opcional
Campo
Tipo
Descripción
shoppingEnabled
booleandefault false
Adds a shopping discovery pass. Set it only for a project that tracks a shopping engine: on any other project the pass spends provider budget on results nothing will use.
country
stringmin length 2, max length 2
ISO 3166-1 alpha-2 country used to localize the discovery.
Respuestas
202 The discovery job was accepted
400 The body is not a JSON object, names an unknown field, or fails validation; or the Idempotency-Key header is missing
401 Missing or invalid API key
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The project is archived, or the organization is archived, or the Idempotency-Key was already used for a different request, or a previous attempt with it ended without a known outcome
429 The organization exceeded ten brand discovery starts per minute, or the key exceeded its request budget
POST /api/v1/organizations/{organizationId}/projects/{projectId}/discovery/keywords
Start a keyword discovery job for a project
Minimum role: manager.
Starts background keyword discovery from free-text seed input and answers 202 with the job to poll; it never returns keywords inline. The job SUGGESTS keywords - it creates no tracked queries and changes nothing in the project, so a completed job is a list to choose from, not work that has been applied.
Queries the project already tracks are excluded from the suggestions automatically; excludeQueries adds more on top for this run only. The organization must be active and hold an entitled subscription, because the run spends provider budget. Ten starts per minute per organization, counted across every key of every member; a retry carrying an Idempotency-Key already answered is served from the record and does not count.
Run tuning is not exposed: the discovery fan-out uses provider defaults.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Must belong to the organization in the path.
Idempotency-KeyObligatorio
header
string
Repeat it to retry a start whose response was lost; the same key returns the same job instead of starting a second one.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
inputObligatorio
stringmax length 10000
Free text describing the keywords or topics to expand.
language
stringmax length 5
Language code. Omit to let the provider detect it from the input.
country
stringmin length 2, max length 2
ISO 3166-1 alpha-2 country. Omit to let the provider infer it.
excludeQueries
string[]
Extra queries to keep out of the suggestions for this run. Duplicates are collapsed, after the entry count has been checked against maxItems. The project tracked queries are excluded whether or not this is sent.
Respuestas
202 The discovery job was accepted
400 The body is not a JSON object, names an unknown field, or fails validation; or the Idempotency-Key header is missing
401 Missing or invalid API key
402 The organization has no entitled subscription
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The project is archived, or the organization is archived, or the Idempotency-Key was already used for a different request, or a previous attempt with it ended without a known outcome
429 The organization exceeded ten discovery starts per minute, or the key exceeded its request budget
curl -X POST "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/discovery/keywords" \
-H "Authorization: Bearer $MENCORO_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"input": "crm for plumbers, field service software",
"language": "es",
"country": "ES",
"excludeQueries": [
""
]
}'
POST /api/v1/organizations/{organizationId}/projects/{projectId}/discovery/prompts
Start a geo prompt discovery job for a project
Minimum role: manager.
Starts background discovery of natural-language prompts - the questions an answer engine gets asked - from free-text seed input, and answers 202 with the job to poll; it never returns prompts inline. The job SUGGESTS prompts: it creates no tracked queries and changes nothing in the project.
country is required here, unlike keyword discovery, because a prompt is a question asked from somewhere and the provider request has no default for it. Queries the project already tracks are excluded automatically; excludeQueries adds more for this run only. The organization must be active and hold an entitled subscription, because the run spends provider budget.
Ten starts per minute per organization, counted across every key of every member; a retry carrying an Idempotency-Key already answered is served from the record and does not count. Run tuning is not exposed: the discovery fan-out uses provider defaults.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
projectIdObligatorio
path
string (uuid)
Must belong to the organization in the path.
Idempotency-KeyObligatorio
header
string
Repeat it to retry a start whose response was lost; the same key returns the same job instead of starting a second one.
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
inputObligatorio
stringmax length 10000
Free text describing the topics to turn into prompts.
countryObligatorio
stringmin length 2, max length 2
ISO 3166-1 alpha-2 country the prompts are asked from.
language
stringmax length 5
Language code. Omit to let the provider detect it from the input.
excludeQueries
string[]
Extra queries to keep out of the suggestions for this run. Duplicates are collapsed, after the entry count has been checked against maxItems. The project tracked queries are excluded whether or not this is sent.
Respuestas
202 The discovery job was accepted
400 The body is not a JSON object, names an unknown field, or fails validation; or the Idempotency-Key header is missing
401 Missing or invalid API key
402 The organization has no entitled subscription
403 The key lacks the write capability
404 No organization or project the caller can access under these ids
409 The project is archived, or the organization is archived, or the Idempotency-Key was already used for a different request, or a previous attempt with it ended without a known outcome
429 The organization exceeded ten discovery starts per minute, or the key exceeded its request budget
curl -X POST "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/projects/$PROJECT_ID/discovery/prompts" \
-H "Authorization: Bearer $MENCORO_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"input": "crm for plumbers, field service software",
"country": "ES",
"language": "es",
"excludeQueries": [
""
]
}'
GET /api/v1/organizations/{organizationId}/invitations
List an organization's invitations
Minimum role: owner.
Returns the invitations issued for this organization, in every state. The invitation token is never returned. status matches the stored state, so an invitation that has passed its expiresAt is still listed as pending until it is transitioned; compare expiresAt to decide. Rows are ordered by the chosen sort field, and invitations sharing the same value keep no guaranteed relative order across pages.
Send Accept: text/csv to receive the same page as a CSV download instead of JSON: same filters, same authorization, same page window and the same maximum of 100 rows. It is this page in another format, not a bulk export, so a whole collection is still read by paging. The CSV carries no total, because a table whose every row is a record has nowhere to put one; read it from the JSON representation of the same request.
Cells beginning with =, +, - or @ are prefixed with an apostrophe so a spreadsheet treats them as text rather than running them as formulas.
POST /api/v1/organizations/{organizationId}/invitations
Invite somebody to an organization
Minimum role: owner.
Sends an invitation email that expires after 14 days. If the address already belongs to an active member the call succeeds and creates nothing - answered as 200 with created=false rather than 201, so a client can tell the two apart. Preview it first; the preview says which of the two will happen.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
X-Mencoro-ConfirmationObligatorio
header
string
Idempotency-KeyObligatorio
header
string
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
email
string (email)
role
owner | manager | viewerdefault "viewer"
Respuestas
200 Nothing was created because the address already belongs to an active member. Not an error: the end state the caller asked for already holds.
201 The invitation that was created. created is true; branch on it rather than on the status code, so one code path handles both answers.
401 Missing or invalid API key
403 The key lacks the organization:manage capability
404 No organization the caller can access under this id
409 The confirmation is invalid, expired, already used, or its effects changed; or a pending invitation already exists for this address
428 No confirmation was sent; preview the operation first
POST /api/v1/organizations/{organizationId}/invitations/{invitationId}/cancel
Cancel a pending invitation
Minimum role: owner.
The link already emailed to the invitee stops working. Only a pending invitation can be cancelled; one that was accepted, rejected or has expired is refused.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
invitationIdObligatorio
path
string (uuid)
X-Mencoro-ConfirmationObligatorio
header
string
Idempotency-KeyObligatorio
header
string
Respuestas
200 The invitation in its new state
401 Missing or invalid API key
403 The key lacks the organization:manage capability
404 No organization or invitation the caller can access under these ids
409 The confirmation is invalid, expired, already used, or its effects changed; or the invitation is not pending
428 No confirmation was sent; preview the operation first
GET /api/v1/organizations/{organizationId}/jobs/{jobId}
Get an asynchronous job
Minimum role: manager.
The status of one asynchronous job started inside this organization, geo prompt discovery, keyword discovery, query clustering, brand discovery or brand-name suggestion, and, once it has completed, its result. Poll it until status is terminal: completed or failed. A null result means the result is not known, either because the job is still in flight or because it failed; it never means the job produced an empty result.
A failed job carries no reason: the stored one is an internal exception message, not a published field. A job started by another organization, a job of a type this API does not publish, and a job id that does not exist all answer 404 alike, so the API never confirms that an inaccessible job exists.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
jobIdObligatorio
path
string (uuid)
Must be a job started inside the organization in the path.
Respuestas
200 The job, and its result once it has completed
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization or job the caller can access under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/jobs/$JOB_ID" \
-H "Authorization: Bearer $MENCORO_API_KEY"
Aggregate counts over every organization the key's owner is an active member of, narrowed to the key's scope. The same set /api/v1/organizations pages through. organizations.total is that set's size; projects.total and projects.active count the projects inside it, archived ones included in the total and excluded from the active figure.
Every value is an exact count: zero means zero, and no value here is ever null or unknown. Per-organization billing and usage figures are not part of this response; read them from the subscription and entitlements operations instead.
Respuestas
200 Counts across the organizations the key can reach
401 Missing or invalid API key
403 The key lacks the read capability, or the user it belongs to is no longer active
curl -X GET "https://api.mencoro.com/api/v1/me/stats" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/members
List an organization's members
Minimum role: owner.
The application exposes this roster twice and the two disagree, its member screen shows it to any viewer, while its non-BFF endpoint requires an owner, so the published API takes the stricter of the two and requires an owner. A membership describes the membership, not the person: names and email addresses are never returned here, and there is no search parameter, because both would turn the roster into a contact export.
Omitting "status" returns active and suspended memberships alike. Sorting by "role" is alphabetical on the role name, not by seniority.
Send Accept: text/csv to receive the same page as a CSV download instead of JSON: same filters, same authorization, same page window and the same maximum of 100 rows. It is this page in another format, not a bulk export, so a whole collection is still read by paging. The CSV carries no total, because a table whose every row is a record has nowhere to put one; read it from the JSON representation of the same request.
Cells beginning with =, +, - or @ are prefixed with an apostrophe so a spreadsheet treats them as text rather than running them as formulas.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
limit
query
integermin 1, max 100, default 20
offset
query
integermin 0, default 0
status
query
active | suspended
Absent means both states.
sortBy
query
joinedAt | roledefault "joinedAt"
sortOrder
query
asc | descdefault "desc"
Respuestas
200 The organization's memberships
400 A parameter was rejected; the details name the field. A limit above 100 is refused, not clamped
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization the caller owns under this id
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/members" \
-H "Authorization: Bearer $MENCORO_API_KEY"
GET /api/v1/organizations/{organizationId}/members/{memberId}
Get one organization membership
Minimum role: owner. The same floor the members listing enforces, because a caller who can page the roster has already seen this record.
Returns the facts of one membership: its role, whether it is active or suspended, and when it was joined. It does NOT describe the person behind it: no name, no email address, no phone number and no profile image, so a membership id can never be turned into a contact lookup. The membership is read from PostgreSQL, the same row at the same freshness the listing publishes.
A membership belonging to another organization answers 404, exactly as an unknown or malformed id does, so the API never confirms that an inaccessible membership exists; the one 403 is a key without the read capability. The response carries no organizationId, it is the one in the path, and no creation timestamp; joinedAt is the membership fact.
No query parameters are accepted.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
memberIdObligatorio
path
string (uuid)
The membership id, not the user id. Must belong to the organization in the path.
Respuestas
200 The membership
401 Missing or invalid API key
403 The key lacks the read capability
404 No organization the caller owns, or no membership of it, under these ids
curl -X GET "https://api.mencoro.com/api/v1/organizations/$MENCORO_ORG_ID/members/$MEMBER_ID" \
-H "Authorization: Bearer $MENCORO_API_KEY"
The role of a suspended member cannot be changed, and the last active owner cannot be demoted. Preview it first: the confirmation is bound to the number of active owners, so another owner being suspended in between invalidates it rather than stranding the organization.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
memberIdObligatorio
path
string (uuid)
X-Mencoro-ConfirmationObligatorio
header
string
Idempotency-KeyObligatorio
header
string
Cuerpo de la petición
application/json, Obligatorio
Campo
Tipo
Descripción
role
owner | manager | viewer
Respuestas
200 The membership in its new state
401 Missing or invalid API key
403 The key lacks the organization:manage capability
404 No organization or membership the caller can access under these ids
409 The confirmation is invalid, expired, already used, or its effects changed; the member is suspended; or this is the last active owner
428 No confirmation was sent; preview the operation first
POST /api/v1/organizations/{organizationId}/members/{memberId}/suspend
Suspend a member
Minimum role: owner.
The member loses access on their very next request, including through any API key they own that is scoped to this organization. The last active owner cannot be suspended.
Parámetros
Nombre
En
Tipo
Descripción
organizationIdObligatorio
path
string (uuid)
memberIdObligatorio
path
string (uuid)
X-Mencoro-ConfirmationObligatorio
header
string
Idempotency-KeyObligatorio
header
string
Respuestas
200 The membership in its new state
401 Missing or invalid API key
403 The key lacks the organization:manage capability
404 No organization or membership the caller can access under these ids
409 The confirmation is invalid, expired, already used, or its effects changed; the member is already suspended; or this is the last active owner
428 No confirmation was sent; preview the operation first
Preview an organization operation and obtain a confirmation
Organization, member and invitation changes need two calls. This one reports the concrete changes, the side effects, the warnings and the conditions, and returns a confirmation valid for five minutes. Send it back in the X-Mencoro-Confirmation header, together with an Idempotency-Key, on the call that performs the operation.
Previewing has no effects of any kind.
Cuerpo de la petición
application/json, Obligatorio