Skip to main content

TOM External API

Programmatic access to TOM survey tabulation, media planning, Reach and plan optimization

Release Notes​

Changes to the TOM External API, newest version first. Within a version, entries are grouped by kind: breaking changes, additions, changes, deprecations and fixes. Deprecated fields and endpoints are announced here before they are removed.

v2.3​

Breaking (pre-adoption)​

These changes alter the values, the properties or the errors of v2 responses. They are made before external integrations adopt v2.3, so each old value or property is replaced by the new one in responses instead of being returned next to it. Requests keep accepting the previous names (see Deprecated). If a client already reads v2 responses, update it.

Carriers replace supports

  • Axes of carriers in POST /api/v2/table/{surveyCode}, POST /api/v2/table/{surveyCode}/html, POST /api/v2/reach/{surveyCode}, the rows of a ranking, the saved tabulation and GET /api/v2/workspace/{workspaceId}/element/{elementId}: axisType SUPPORTS is now CARRIERS and the property supports is now carriers. The id of the axis of a ranking (AXIS_SUPPORTS) does not change: it is opaque.
  • type of each carrier, also in the rows of a ranking and of an evaluation: SUPPORT is now CARRIER, SUPPORT_JOINT is CARRIER_JOINT, TOTAL_MEDIA_SUPPORT is TOTAL_MEDIA and TOTAL_SUPPORT is TOTAL. A carrier whose kind has no public name is returned without type.
  • The total of all media is TOTAL_MEDIA, in the id and in the label of the axis and in the items of matrixList.
  • GET /api/v2/survey/{surveyCode}/carriers and the tree queries: the type of a carrier is now CARRIER (it was SUPPORT) and the treeType of a tree node is now CARRIERS (it was SOPORTES).
  • Carriers no longer return subtype. The audience model they used to carry there is now audienceModel, and its values changed: DEFAULT is STANDARD and COMSCORE is DIGITAL_MEASUREMENT; POISSON, ITALIAN_DIARY_INTERNET and ITALIAN_DIARY do not change.
  • Tree nodes: attrs is replaced by carrierInfo (medium, info, time, day and duration, only on carriers) and transKey is no longer returned.
  • Optimization result: supports of each plan is now carriers.
  • Reference schemas: SupportsAxis is now CarriersAxis, OptimizationCandidateSupport is OptimizationCandidateCarrier and OptimizationPlanSupport is OptimizationPlanCarrier. The four listings return the new CatalogItem schema, with the same JSON as before except for the carrier changes above. The Carrier schema is now the carrier of table, Reach and result axes, and the carriers of a ranking, an evaluation or a response curve request are RankingCarrier.

Other values and properties

  • tableType in responses: BREAKDOWN_SUPPORTS is now BREAKDOWN_CARRIERS, in the table of a workspace element and in the messageType of a diagnostic. A diagnostic of a kind that has no public name is returned without messageType.
  • level of a diagnostic: CRITICAL, which was never produced, is now reported as ERROR.
  • GET /api/v2/statistics?tableType=RANKING no longer lists PLAN_TOTAL and PLAN: a ranking never builds those columns, so they could never be requested. The plan columns of a ranking (PLAN_1, PLAN_2, ...) are results, and the figures of each plan as a whole are in the evaluation, in the row of the plan (type: MEDIA_PLAN).
  • type and subtype of variables and type of categories (in listings, axes and the items of matrixList) use the public values. A SPLIT or TOTAL category inside the categories of a variable, and the subtypes TOTAL and WEIGHTED of user variables, are omitted.
  • Schema only, with no change in the JSON that is returned: the table response no longer declares the request fields tableType, target, dataType, locale, decimals and extraParams; ReachStatistic.code is hidden (it is still returned, with the same value as id: use id); Category.subtype, excludeCustoms and language of the tree query are hidden. A client that still sends them gets no error.

Survey names show the alias

  • The name of a survey is now the one the user sees in TOM: the alias the user gave the survey, otherwise its default alias, otherwise the catalog name. Before, it was always the catalog name. This applies to description in GET /api/v2/users/surveys and in the surveys of GET /api/v2/workspace/{workspaceId}, surveyDescription in GET /api/v2/workspaces and GET /api/v2/workspace/{workspaceId}, and sourceLabel in the validInSources of POST /api/v2/workspace/{workspaceId}/survey/{surveyCode}/tree/query/custom. When the name cannot be resolved, surveyDescription keeps the name saved with the workspace and sourceLabel keeps its previous value.
  • An alias is free text chosen by each user, so the same survey can have different names for different API keys, two surveys can share a name, and a name can be longer than a catalog name. Identify a survey by its code, never by its name.

Survey waves and Reach trends

  • The survey waves of a SOURCES axis are strict: an unknown field in a wave or in its weight returns 400 AE_ERR_411.
  • weeks, weight and selected of a survey wave are applied, so the figures of a TREND that already sent them can change: the weeks and the weighting decide the data of each wave, and selected decides the wave shown in PLANES. In a REACH_TREND the weeks and the weighting only decide whether a wave is calculated, and they do not change the figures.
  • REACH_TREND in POST /api/v2/table/{surveyCode} and POST /api/v2/table/{surveyCode}/html requires the Reach module, like the other Reach types: without it, 403 AE_ERR_408.

Errors

  • An invalid tableType in GET /api/v2/statistics and an invalid type in GET /api/v2/workspace/{workspaceId} now return 400 AE_ERR_401 (they returned 404).
  • An unknown method.type, treeType, types or searchField in a tree query now returns 400 AE_ERR_401 (it returned 400 without a body).
  • AE_ERR_401 lists only public values. For example, tableType lists six values and category.type four.
  • PLAN_TOTAL and PLAN in the statistics of POST /api/v2/survey/{surveyCode}/ranking now return 400 AE_ERR_402 before the calculation, like PLAN_1. They returned AE_ERR_403, whose message pointed to the survey.
  • TW_ERR_500 in /api/v2 has a fixed message in English, The X-API-Key value does not identify a TOM user. The errorCode and the status do not change.
  • The messages of AE_ERR_409, AE_ERR_410, AE_ERR_411 and AE_ERR_412 name the public values and the schema of the object, never an internal class name. The message of AE_ERR_410 for an optimization is now At least one candidate carrier is required.
  • A target with neither a non-blank id nor a non-blank filterTgl, for example "target": {}, in POST /api/v2/table/{surveyCode}, POST /api/v2/table/{surveyCode}/html and POST /api/v2/reach/{surveyCode} now returns 400 AE_ERR_405. Before, it was ignored and the table was calculated without a target.
  • AE_ERR_405 in ranking, evaluation, evaluation save and response curve now means only that target or targetBase has no identifier, and its message names the field.

Added​

  • CUSTOM_VAR and TARGET_VAR are accepted in VARIABLES axes of POST /api/v2/table/{surveyCode}, POST /api/v2/table/{surveyCode}/html and POST /api/v2/reach/{surveyCode}. A TARGET_VAR can be sent by saved target id or by filterTgl. In responses, a TARGET_VAR calculated from a TGL expression includes its filterTgl (v1 never returns it), so the axis can be sent back unchanged. In TREND tables a CUSTOM_VAR may still be omitted from the response.
  • audienceModel and carrierInfo on the carrier nodes of the carriers listing and of the tree queries.
  • The reference publishes the enumerated values of the API (for example AxisKind, CarrierType, TableRequestKind, TreeType and AudienceModel) as schemas of their own, with the meaning of each value.
  • targetBase in POST /api/v2/reach/{surveyCode} and in the request of POST /api/v2/survey/{surveyCode}/optimizations: the population base, the reference universe of the percentages. It is identified by a saved target id or by an inline expression in filterTgl.
  • targetBase in POST /api/v2/table/{surveyCode} and POST /api/v2/table/{surveyCode}/html, for any tableType, and in POST /api/v2/survey/{surveyCode}/ranking, .../evaluation, .../evaluation/save/{workspaceId} and .../response-curve. A saved evaluation keeps its base. A base id is not looked up beforehand: if it cannot be resolved, the calculation engine returns its error, except in a TREND table, which leaves the base out and reports it in diagnostics.
  • GET /api/v2/workspace/{workspaceId}/element/{elementId} returns, in the table of a tabulation or a Reach table, the saved target and, when the base was saved applied, the targetBase, as they were saved: id when they were saved by id, filterTgl when there is a saved TGL expression or when its saved conditions can be written as one, and label when there is one. With resolve=TGL, a target or a base saved by id also returns its filterTgl. A target or a base that cannot be returned in one of these forms comes with its label only and is listed in notReproducible: sent back unchanged, it returns 400 AE_ERR_405.
  • filterTgl in the target of an optimization, the same name that the rest of the API uses for an inline TGL expression.
  • DELETE /api/v2/workspace/{workspaceId}: delete a workspace and everything it contains. Only the owner can delete. The answer is 204 with no body; the delete is physical and cannot be undone.
  • DELETE /api/v2/workspace/{workspaceId}/element/{elementId}: delete a tabulation, a Reach table, a target, a user variable or a saved evaluation of a workspace. The id of a saved evaluation is the one returned when it was saved. Other types answer 400 AE_ERR_420. Dependencies are not checked: the elements that used a deleted target keep their saved result.
  • New error codes for the delete operations: AE_ERR_417 (404, workspace not found or not visible), AE_ERR_418 (403, workspace shared with you, not owned), AE_ERR_419 (404, element not found in the workspace) and AE_ERR_420 (400, type that cannot be deleted). Repeating a delete answers 404.
  • orderBy (NAME or LAST_UPDATED) and ascending in GET /api/v2/workspaces, to get the list in another order. An invalid value returns 400 AE_ERR_401.
  • lastUpdated, ownership (OWN, SHARED_BY_ME or SHARED_WITH_ME) and ownerName on each workspace of GET /api/v2/workspaces. A SHARED_WITH_ME workspace is read only. GET /api/v2/workspace/{workspaceId} does not return these fields.
  • originalDescription on the surveys of GET /api/v2/users/surveys and of GET /api/v2/workspace/{workspaceId}: the catalog name of the survey, without any alias. Use description to show a survey and originalDescription to classify or search it. v1 never returns it, although the shared Survey schema of the v1 reference now declares it as optional.
  • REACH_TREND, a public tableType: the statistics of a REACH_TABLE compared across survey waves, in POST /api/v2/reach/{surveyCode}, POST /api/v2/table/{surveyCode} and POST /api/v2/table/{surveyCode}/html. It takes a CARRIERS axis, a SOURCES axis with the survey waves and a DIFFERENCES axis. A survey of the path without Reach returns 400 RC_ERR_100 before calculating; another wave that cannot be calculated comes without values and with a WARNING diagnostic.
  • differences in GET /api/v2/survey/{surveyCode}/reach-capabilities: the ids of the DIFFERENCES axis of a REACH_TREND, keyed REACH_TREND. statistics.REACH_TREND lists the ids of its STATISTICS axis.
  • targetMedia and diaryFilters in POST /api/v2/table/{surveyCode} and POST /api/v2/table/{surveyCode}/html, with a Reach tableType. A Reach table read from a workspace can be sent unchanged to any of the three operations.
  • GET /api/v2/survey/{surveyCode}/weeks-and-weights: the weeks and the weightings of a survey, the values that weeks and weight take.
  • weights on each survey of GET /api/v2/users/surveys: the weightings of the survey, the same ones that GET /api/v2/survey/{surveyCode}/weeks-and-weights returns, with the default one marked isDefault: true. It is an empty list when the survey has none. v1 and the surveys of GET /api/v2/workspace/{workspaceId} do not return it.
  • weeks and weight of the table, in TABULATION and REACH_TABLE. They are checked against the survey before calculating, and a value the survey does not have returns 400 AE_ERR_400. In a REACH_TABLE they do not change the Reach figures.
  • weeks and weight of each survey wave of a TREND or REACH_TREND. A wave with a week or a weighting its survey does not have is left out with a TR_ERR_107 diagnostic, and a survey without weeks or without weightings ignores them.
  • axis in GET /api/v2/statistics (STATISTICS or DIFFERENCES): with tableType=TREND, the ids that each axis of a trend takes.
  • GET /api/v2/workspace/{workspaceId}/element/{elementId} returns the Reach settings of a Reach table (targetMedia and diaryFilters), and a REACH_TREND complete, with its SOURCES and DIFFERENCES axes; a SOURCES axis saved as a group of surveys comes expanded, one wave per member. The weeks and weight of a TABULATION or REACH_TABLE are the effective ones, and extraParams comes as it was saved, trendCategoriesMode included.
  • notReproducible in GET /api/v2/workspace/{workspaceId}/element/{elementId}: what the request cannot carry as it was saved, with a field and a reason. It marks a target or targetBase that cannot be written with id or filterTgl, an item of a CUSTOM_DIARY_EDGE axis that grouped several values (GROUPED_ITEM, left out of the axis) and the total item of a diary edge axis (TOTAL_ITEM).
  • extraParams.trendCategoriesMode (ONLY_ACTIVE_SOURCE_CATEGORIES, ALL or VALID_IN_ALL_SOURCES): the categories that enter each wave of a TREND or REACH_TREND. Any other value returns 400 TR_ERR_106.
  • The TR_ERR codes of trends are documented: TR_ERR_101, TR_ERR_103, TR_ERR_105, TR_ERR_106 and TR_ERR_109 as 400 errors, and TR_ERR_107 as a diagnostic of a 200 response.
  • Errors the API already returned are documented in the operations that return them, with no change in the API:
    • 400: TG_ERR_113, TG_ERR_115, TGL_ERR_101, SP_ERR_101, EV_ERR_103, VA_ERR_102, ST_ERR_122, CV_ERR_109, TB_ERR_104, T_ERR_104 and T_ERR_106.
    • 422 TGL_INVALID in table, Reach, ranking, evaluation, evaluation save and response curve. As in targets, its body comes as application/json.
    • 401 SO_ERR_203 in the response curve, and 406 E406 in the HTML table.
    • The 405, 406 and 415 that any operation returns before it runs (see Errors).

Changed​

  • The ids of the statistics of each table type are fixed: an id that exists keeps its name and its meaning. New statistics can be added, so a client must not fail on an id it does not know. The columns PLAN_n of a ranking are results, not statistics to request.

  • A null or blank element in the types of a tree query is now AE_ERR_401 (before, it reached the platform).

  • POST /api/v2/survey/{surveyCode}/tree/query with method.type ALL and a non-empty nodesId or nodes now returns 400 AE_ERR_400 at once (it returned 500 after several seconds). ALL takes no anchors: use NODE to fetch specific nodes, or NODE_HIERARCHY to search the branch under a node. The custom tree query does not change.

  • The descriptions and examples of the reference are in English.

  • One rule for the target and the targetBase of every v2 calculation (table, HTML table, Reach, ranking, evaluation, evaluation save and response curve): identify them by id or by filterTgl; with both, filterTgl is used and id is ignored; with neither, 400 AE_ERR_405. A TARGET_VAR in a VARIABLES axis also uses filterTgl when both are sent. In ranking, evaluation, evaluation save and response curve, sending both used to return 400 AE_ERR_405 and now returns 200.

  • Ranking, evaluation, evaluation save and response curve did not have a targetBase and ignored it. It is now applied, so the figures of the requests that already sent one change.

  • POST /api/v2/reach/{surveyCode} requires tableType, which must be REACH_TABLE, REACH_DUPLICATION or REACH_TREND. A request without it, or with any other value, returns 400 AE_ERR_401 and the message lists the valid values. A targetBase with neither a non-blank id nor a non-blank filterTgl returns 400 AE_ERR_405. A base that cannot be resolved returns the error of the calculation engine.

  • The request of POST /api/v2/survey/{surveyCode}/optimizations is strict: an unknown field in the request, in target, in targetBase, in a candidate carrier or in an objective returns 400 AE_ERR_400, and the message names the field and the object. A target or a targetBase with both id and filterTgl, or with neither, returns 400 AE_ERR_411, and the message names the field.

  • In VARIABLES axes of POST /api/v2/table/{surveyCode}, POST /api/v2/table/{surveyCode}/html and POST /api/v2/reach/{surveyCode}, a variable that cannot be converted is rejected with 400 (AE_ERR_412 when subtype, id or filterTgl is missing, AE_ERR_416 for an unsupported combination). Both errors locate the axis, dimension, variable, field and offending value (if any):

    • Some requests that returned an incomplete 200 (the variable was silently dropped) now return 400: a VAR or CUSTOM_VAR without subtype, or a CUSTOM_VAR without id or with subtype TEXT, LOGIC, TOTAL or WEIGHTED
    • Requests that returned 500 now return 400: a VAR without id gives AE_ERR_412 and a VAR with subtype TEXT gives AE_ERR_416
    • A blank subtype now returns AE_ERR_412 instead of 401
    • A TARGET_VAR without id or filterTgl still returns 400, but the errorCode changes from TG_ERR_115 to AE_ERR_412
  • GET /api/v2/workspaces returns the workspaces in the order the user chose in the workspaces view of the TOM web application; without one, the most recently updated first. Before, it returned the user's own workspaces by name and then the shared ones. To get an alphabetical list, send orderBy=NAME.

  • diagnostics.level is the worst level among the one of the calculation and the level of each diagnostic, so it is never lower than any of them.

  • REACH_TREND is a new value of tableType in responses (TableKind), for example in the table of a workspace element. A client that reads tableType must accept it.

  • targetMedia or diaryFilters with a tableType that is not a Reach type return 400 AE_ERR_400, and the message names the field. They returned AE_ERR_411.

  • Client errors in v2 are answered with 400 and a code of this API, never with 500. A body value of the wrong JSON type, or a JSON array where an object goes, returns AE_ERR_400 on every v2 operation, and the message names the field by its path. A null element or one without id in a list returns AE_ERR_412, a null dimension AE_ERR_413, and an unknown dimension id or a public value sent as a number AE_ERR_401. A blank X-API-Key is treated as a missing one (401 E401).

  • The body of a 422 TGL_INVALID carries status 422. It carried 500.

Deprecated​

These names are still accepted in requests. They are not documented in the reference, the API never returns them, and their removal will be announced here in advance. Use the current names (see Deprecated names).

  • SUPPORTS (axisType) and supports (the property of an axis and of an optimization request): use CARRIERS and carriers.
  • SUPPORT, SUPPORT_JOINT, TOTAL_MEDIA_SUPPORT and FAMILY (type of a carrier): use CARRIER, CARRIER_JOINT, TOTAL_MEDIA and FOLDER.
  • BREAKDOWN_SUPPORTS (tableType): use BREAKDOWN_CARRIERS.
  • In tree queries, SOPORTES (treeType), SUPPORT (types) and NODE_UUID, NODE_ID and NODE_DESC (searchField): use CARRIERS, CARRIER, ID, CODE and LABEL.
  • base (the population base of a Reach request): use targetBase. Do not send both: the last one in the body is used.
  • tgl (the inline expression of the target and the targetBase of an optimization): use filterTgl. Do not send both in one object: the last one is used.

Fixed​

  • The population base of POST /api/v2/reach/{surveyCode} was accepted but not applied: the percentages were always calculated over the whole universe of the survey. It is now applied, so the figures of the requests that sent a base change.
  • The target of an optimization is now applied as a filter of the calculation, by saved id or by filterTgl. Before, a target sent by saved id could end the job FAILED.

v2.2​

Added​

  • POST /api/v2/survey/{surveyCode}/tree/query — Query the variables or carriers tree level by level (root, expand, search). It answers 206 Partial Content when the result is truncated
  • POST /api/v2/workspace/{workspaceId}/survey/{surveyCode}/tree/query/custom — Query the custom tree of a workspace level by level
  • GET /api/v2/workspace/{workspaceId}/element/{elementId} — Get a workspace element as a reusable request
  • POST /api/v2/survey/{surveyCode}/response-curve — Calculate the response curve of a media plan
  • POST /api/v2/survey/{surveyCode}/optimizations — Submit a media plan optimization
  • GET /api/v2/optimizations/{jobId} — Get the status of an optimization
  • GET /api/v2/optimizations/{jobId}/result — Get the result of an optimization
  • Typed axes in table requests and responses: every axis carries an axisType and accepts only the fields of that type
  • Split axes: a VARIABLES axis with split: true linked to a CATEGORIES axis
  • filter and capabilities of the diary edges in GET /api/v2/survey/{surveyCode}/reach-capabilities
  • GET /api/v2/workspace/{workspaceId} accepts the type filter to choose which element lists to return
  • Table responses can include an optional diagnostics object with the business diagnostics of the calculation, for example a user variable or a target that could not be resolved in the survey. It is present only when there is something to report.

Changed​

  • GET /api/v2/survey/{surveyCode}/variables and /carriers now return 403 when the survey is not accessible to the user (not contracted, disabled or loading, or non-existent)
  • GET /api/v2/workspace/{workspaceId}/survey/{surveyCode}/tabulation/{elementId} returns the table model of the calculation endpoints (matrixList and typed axes) instead of a single matrix. See the Migration guide

v2.1​

Added​

  • dataType, locale and decimals in table requests, to choose how cells are returned and formatted
  • CARRIER_JOINT carriers list their member carriers in ids
  • GET /api/v2/workspace/{workspaceId} returns the saved Reach tables in reachTables
  • GET /api/v2/statistics returns a description for each statistic

v2.0​

Added​

  • POST /api/v2/reach/{surveyCode} — Calculate a Reach table
  • GET /api/v2/survey/{surveyCode}/reach-capabilities — Get the Reach capabilities of a survey
  • POST /api/v2/table/{surveyCode}/html — Calculate a table as HTML
  • targetMedia in Reach requests

Changed​

  • Calculations and the statistics catalog check the application module of the user's profile (Tabulation, Study or Reach). A user without the required module gets 403 (AE_ERR_408)

See the full changelog →