Getting started
From an API key to your first calculated table.
Core concepts
Surveys, variables, carriers, workspaces, targets and tables: the vocabulary of the API.
Building tables
Define axes, variables, statistics and planes, and read the response.
Reach
Reach and duplication tables on consumption-diary surveys.
Media planning
Rank carriers, evaluate media plans and calculate response curves.
Asynchronous optimization
Submit a media plan optimization, poll it and read the result.
Errors and troubleshooting
The error body, every error code and what to do about it.
TGL guide
The expression language that defines audiences.
Migrate from v1
What changes between /api/v1 and /api/v2, and how to adapt your client.
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 andGET /api/v2/workspace/{workspaceId}/element/{elementId}:axisTypeSUPPORTSis nowCARRIERSand the propertysupportsis nowcarriers. Theidof the axis of a ranking (AXIS_SUPPORTS) does not change: it is opaque. typeof each carrier, also in the rows of a ranking and of an evaluation:SUPPORTis nowCARRIER,SUPPORT_JOINTisCARRIER_JOINT,TOTAL_MEDIA_SUPPORTisTOTAL_MEDIAandTOTAL_SUPPORTisTOTAL. A carrier whose kind has no public name is returned withouttype.- The total of all media is
TOTAL_MEDIA, in theidand in the label of the axis and in theitemsofmatrixList. GET /api/v2/survey/{surveyCode}/carriersand the tree queries: thetypeof a carrier is nowCARRIER(it wasSUPPORT) and thetreeTypeof a tree node is nowCARRIERS(it wasSOPORTES).- Carriers no longer return
subtype. The audience model they used to carry there is nowaudienceModel, and its values changed:DEFAULTisSTANDARDandCOMSCOREisDIGITAL_MEASUREMENT;POISSON,ITALIAN_DIARY_INTERNETandITALIAN_DIARYdo not change. - Tree nodes:
attrsis replaced bycarrierInfo(medium,info,time,dayandduration, only on carriers) andtransKeyis no longer returned. - Optimization result:
supportsof each plan is nowcarriers. - Reference schemas:
SupportsAxisis nowCarriersAxis,OptimizationCandidateSupportisOptimizationCandidateCarrierandOptimizationPlanSupportisOptimizationPlanCarrier. The four listings return the newCatalogItemschema, with the same JSON as before except for the carrier changes above. TheCarrierschema is now the carrier of table, Reach and result axes, and the carriers of a ranking, an evaluation or a response curve request areRankingCarrier.
Other values and properties
tableTypein responses:BREAKDOWN_SUPPORTSis nowBREAKDOWN_CARRIERS, in the table of a workspace element and in themessageTypeof a diagnostic. A diagnostic of a kind that has no public name is returned withoutmessageType.levelof a diagnostic:CRITICAL, which was never produced, is now reported asERROR.GET /api/v2/statistics?tableType=RANKINGno longer listsPLAN_TOTALandPLAN: 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).typeandsubtypeof variables andtypeof categories (in listings, axes and theitemsofmatrixList) use the public values. ASPLITorTOTALcategory inside the categories of a variable, and the subtypesTOTALandWEIGHTEDof 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,decimalsandextraParams;ReachStatistic.codeis hidden (it is still returned, with the same value asid: useid);Category.subtype,excludeCustomsandlanguageof 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
descriptioninGET /api/v2/users/surveysand in thesurveysofGET /api/v2/workspace/{workspaceId},surveyDescriptioninGET /api/v2/workspacesandGET /api/v2/workspace/{workspaceId}, andsourceLabelin thevalidInSourcesofPOST /api/v2/workspace/{workspaceId}/survey/{surveyCode}/tree/query/custom. When the name cannot be resolved,surveyDescriptionkeeps the name saved with the workspace andsourceLabelkeeps 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
SOURCESaxis are strict: an unknown field in a wave or in itsweightreturns400AE_ERR_411. weeks,weightandselectedof a survey wave are applied, so the figures of aTRENDthat already sent them can change: the weeks and the weighting decide the data of each wave, andselecteddecides the wave shown inPLANES. In aREACH_TRENDthe weeks and the weighting only decide whether a wave is calculated, and they do not change the figures.REACH_TRENDinPOST /api/v2/table/{surveyCode}andPOST /api/v2/table/{surveyCode}/htmlrequires the Reach module, like the other Reach types: without it,403AE_ERR_408.
Errors
- An invalid
tableTypeinGET /api/v2/statisticsand an invalidtypeinGET /api/v2/workspace/{workspaceId}now return400AE_ERR_401(they returned404). - An unknown
method.type,treeType,typesorsearchFieldin a tree query now returns400AE_ERR_401(it returned400without a body). AE_ERR_401lists only public values. For example,tableTypelists six values andcategory.typefour.PLAN_TOTALandPLANin thestatisticsofPOST /api/v2/survey/{surveyCode}/rankingnow return400AE_ERR_402before the calculation, likePLAN_1. They returnedAE_ERR_403, whose message pointed to the survey.TW_ERR_500in/api/v2has a fixed message in English,The X-API-Key value does not identify a TOM user.TheerrorCodeand the status do not change.- The messages of
AE_ERR_409,AE_ERR_410,AE_ERR_411andAE_ERR_412name the public values and the schema of the object, never an internal class name. The message ofAE_ERR_410for an optimization is nowAt least one candidate carrier is required. - A
targetwith neither a non-blankidnor a non-blankfilterTgl, for example"target": {}, inPOST /api/v2/table/{surveyCode},POST /api/v2/table/{surveyCode}/htmlandPOST /api/v2/reach/{surveyCode}now returns400AE_ERR_405. Before, it was ignored and the table was calculated without a target. AE_ERR_405in ranking, evaluation, evaluation save and response curve now means only thattargetortargetBasehas no identifier, and its message names the field.
Added
CUSTOM_VARandTARGET_VARare accepted inVARIABLESaxes ofPOST /api/v2/table/{surveyCode},POST /api/v2/table/{surveyCode}/htmlandPOST /api/v2/reach/{surveyCode}. ATARGET_VARcan be sent by saved targetidor byfilterTgl. In responses, aTARGET_VARcalculated from a TGL expression includes itsfilterTgl(v1 never returns it), so the axis can be sent back unchanged. InTRENDtables aCUSTOM_VARmay still be omitted from the response.audienceModelandcarrierInfoon 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,TreeTypeandAudienceModel) as schemas of their own, with the meaning of each value. targetBaseinPOST /api/v2/reach/{surveyCode}and in the request ofPOST /api/v2/survey/{surveyCode}/optimizations: the population base, the reference universe of the percentages. It is identified by a saved targetidor by an inline expression infilterTgl.targetBaseinPOST /api/v2/table/{surveyCode}andPOST /api/v2/table/{surveyCode}/html, for anytableType, and inPOST /api/v2/survey/{surveyCode}/ranking,.../evaluation,.../evaluation/save/{workspaceId}and.../response-curve. A saved evaluation keeps its base. A baseidis not looked up beforehand: if it cannot be resolved, the calculation engine returns its error, except in aTRENDtable, which leaves the base out and reports it indiagnostics.GET /api/v2/workspace/{workspaceId}/element/{elementId}returns, in thetableof a tabulation or a Reach table, the savedtargetand, when the base was saved applied, thetargetBase, as they were saved:idwhen they were saved by id,filterTglwhen there is a saved TGL expression or when its saved conditions can be written as one, andlabelwhen there is one. Withresolve=TGL, a target or a base saved byidalso returns itsfilterTgl. A target or a base that cannot be returned in one of these forms comes with itslabelonly and is listed innotReproducible: sent back unchanged, it returns400AE_ERR_405.filterTglin thetargetof 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 is204with 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. Theidof a saved evaluation is the one returned when it was saved. Other types answer400AE_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) andAE_ERR_420(400, type that cannot be deleted). Repeating a delete answers404. orderBy(NAMEorLAST_UPDATED) andascendinginGET /api/v2/workspaces, to get the list in another order. An invalid value returns400AE_ERR_401.lastUpdated,ownership(OWN,SHARED_BY_MEorSHARED_WITH_ME) andownerNameon each workspace ofGET /api/v2/workspaces. ASHARED_WITH_MEworkspace is read only.GET /api/v2/workspace/{workspaceId}does not return these fields.originalDescriptionon the surveys ofGET /api/v2/users/surveysand ofGET /api/v2/workspace/{workspaceId}: the catalog name of the survey, without any alias. Usedescriptionto show a survey andoriginalDescriptionto classify or search it. v1 never returns it, although the sharedSurveyschema of the v1 reference now declares it as optional.REACH_TREND, a publictableType: the statistics of aREACH_TABLEcompared across survey waves, inPOST /api/v2/reach/{surveyCode},POST /api/v2/table/{surveyCode}andPOST /api/v2/table/{surveyCode}/html. It takes aCARRIERSaxis, aSOURCESaxis with the survey waves and aDIFFERENCESaxis. A survey of the path without Reach returns400RC_ERR_100before calculating; another wave that cannot be calculated comes without values and with aWARNINGdiagnostic.differencesinGET /api/v2/survey/{surveyCode}/reach-capabilities: the ids of theDIFFERENCESaxis of aREACH_TREND, keyedREACH_TREND.statistics.REACH_TRENDlists the ids of itsSTATISTICSaxis.targetMediaanddiaryFiltersinPOST /api/v2/table/{surveyCode}andPOST /api/v2/table/{surveyCode}/html, with a ReachtableType. 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 thatweeksandweighttake.weightson each survey ofGET /api/v2/users/surveys: the weightings of the survey, the same ones thatGET /api/v2/survey/{surveyCode}/weeks-and-weightsreturns, with the default one markedisDefault: true. It is an empty list when the survey has none. v1 and thesurveysofGET /api/v2/workspace/{workspaceId}do not return it.weeksandweightof the table, inTABULATIONandREACH_TABLE. They are checked against the survey before calculating, and a value the survey does not have returns400AE_ERR_400. In aREACH_TABLEthey do not change the Reach figures.weeksandweightof each survey wave of aTRENDorREACH_TREND. A wave with a week or a weighting its survey does not have is left out with aTR_ERR_107diagnostic, and a survey without weeks or without weightings ignores them.axisinGET /api/v2/statistics(STATISTICSorDIFFERENCES): withtableType=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 (targetMediaanddiaryFilters), and aREACH_TRENDcomplete, with itsSOURCESandDIFFERENCESaxes; aSOURCESaxis saved as a group of surveys comes expanded, one wave per member. Theweeksandweightof aTABULATIONorREACH_TABLEare the effective ones, andextraParamscomes as it was saved,trendCategoriesModeincluded.notReproducibleinGET /api/v2/workspace/{workspaceId}/element/{elementId}: what the request cannot carry as it was saved, with afieldand areason. It marks atargetortargetBasethat cannot be written withidorfilterTgl, an item of aCUSTOM_DIARY_EDGEaxis 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,ALLorVALID_IN_ALL_SOURCES): the categories that enter each wave of aTRENDorREACH_TREND. Any other value returns400TR_ERR_106.- The
TR_ERRcodes of trends are documented:TR_ERR_101,TR_ERR_103,TR_ERR_105,TR_ERR_106andTR_ERR_109as400errors, andTR_ERR_107as a diagnostic of a200response. - 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_104andT_ERR_106.422TGL_INVALIDin table, Reach, ranking, evaluation, evaluation save and response curve. As in targets, its body comes asapplication/json.401SO_ERR_203in the response curve, and406E406in the HTML table.- The
405,406and415that 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_nof a ranking are results, not statistics to request. -
A null or blank element in the
typesof a tree query is nowAE_ERR_401(before, it reached the platform). -
POST /api/v2/survey/{surveyCode}/tree/querywithmethod.typeALLand a non-emptynodesIdornodesnow returns400AE_ERR_400at once (it returned500after several seconds).ALLtakes no anchors: useNODEto fetch specific nodes, orNODE_HIERARCHYto 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
targetand thetargetBaseof every v2 calculation (table, HTML table, Reach, ranking, evaluation, evaluation save and response curve): identify them byidor byfilterTgl; with both,filterTglis used andidis ignored; with neither,400AE_ERR_405. ATARGET_VARin aVARIABLESaxis also usesfilterTglwhen both are sent. In ranking, evaluation, evaluation save and response curve, sending both used to return400AE_ERR_405and now returns200. -
Ranking, evaluation, evaluation save and response curve did not have a
targetBaseand ignored it. It is now applied, so the figures of the requests that already sent one change. -
POST /api/v2/reach/{surveyCode}requirestableType, which must beREACH_TABLE,REACH_DUPLICATIONorREACH_TREND. A request without it, or with any other value, returns400AE_ERR_401and the message lists the valid values. AtargetBasewith neither a non-blankidnor a non-blankfilterTglreturns400AE_ERR_405. A base that cannot be resolved returns the error of the calculation engine. -
The request of
POST /api/v2/survey/{surveyCode}/optimizationsis strict: an unknown field in the request, intarget, intargetBase, in a candidate carrier or in an objective returns400AE_ERR_400, and the message names the field and the object. Atargetor atargetBasewith bothidandfilterTgl, or with neither, returns400AE_ERR_411, and the message names the field. -
In
VARIABLESaxes ofPOST /api/v2/table/{surveyCode},POST /api/v2/table/{surveyCode}/htmlandPOST /api/v2/reach/{surveyCode}, a variable that cannot be converted is rejected with400(AE_ERR_412whensubtype,idorfilterTglis missing,AE_ERR_416for 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 return400: aVARorCUSTOM_VARwithoutsubtype, or aCUSTOM_VARwithoutidor withsubtypeTEXT,LOGIC,TOTALorWEIGHTED - Requests that returned
500now return400: aVARwithoutidgivesAE_ERR_412and aVARwithsubtypeTEXTgivesAE_ERR_416 - A blank
subtypenow returnsAE_ERR_412instead of401 - A
TARGET_VARwithoutidorfilterTglstill returns400, but theerrorCodechanges fromTG_ERR_115toAE_ERR_412
- Some requests that returned an incomplete
-
GET /api/v2/workspacesreturns 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, sendorderBy=NAME. -
diagnostics.levelis the worst level among the one of the calculation and thelevelof each diagnostic, so it is never lower than any of them. -
REACH_TRENDis a new value oftableTypein responses (TableKind), for example in thetableof a workspace element. A client that readstableTypemust accept it. -
targetMediaordiaryFilterswith atableTypethat is not a Reach type return400AE_ERR_400, and the message names the field. They returnedAE_ERR_411. -
Client errors in v2 are answered with
400and a code of this API, never with500. A body value of the wrong JSON type, or a JSON array where an object goes, returnsAE_ERR_400on every v2 operation, and the message names the field by its path. Anullelement or one withoutidin a list returnsAE_ERR_412, anulldimensionAE_ERR_413, and an unknown dimensionidor a public value sent as a numberAE_ERR_401. A blankX-API-Keyis treated as a missing one (401E401). -
The body of a
422TGL_INVALIDcarriesstatus422. It carried500.
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) andsupports(the property of an axis and of an optimization request): useCARRIERSandcarriers.SUPPORT,SUPPORT_JOINT,TOTAL_MEDIA_SUPPORTandFAMILY(typeof a carrier): useCARRIER,CARRIER_JOINT,TOTAL_MEDIAandFOLDER.BREAKDOWN_SUPPORTS(tableType): useBREAKDOWN_CARRIERS.- In tree queries,
SOPORTES(treeType),SUPPORT(types) andNODE_UUID,NODE_IDandNODE_DESC(searchField): useCARRIERS,CARRIER,ID,CODEandLABEL. base(the population base of a Reach request): usetargetBase. Do not send both: the last one in the body is used.tgl(the inline expression of thetargetand thetargetBaseof an optimization): usefilterTgl. 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
targetof an optimization is now applied as a filter of the calculation, by savedidor byfilterTgl. Before, a target sent by savedidcould end the jobFAILED.
v2.2
Added
POST /api/v2/survey/{surveyCode}/tree/query— Query the variables or carriers tree level by level (root, expand, search). It answers206 Partial Contentwhen the result is truncatedPOST /api/v2/workspace/{workspaceId}/survey/{surveyCode}/tree/query/custom— Query the custom tree of a workspace level by levelGET /api/v2/workspace/{workspaceId}/element/{elementId}— Get a workspace element as a reusable requestPOST /api/v2/survey/{surveyCode}/response-curve— Calculate the response curve of a media planPOST /api/v2/survey/{surveyCode}/optimizations— Submit a media plan optimizationGET /api/v2/optimizations/{jobId}— Get the status of an optimizationGET /api/v2/optimizations/{jobId}/result— Get the result of an optimization- Typed axes in table requests and responses: every axis carries an
axisTypeand accepts only the fields of that type - Split axes: a
VARIABLESaxis withsplit: truelinked to aCATEGORIESaxis filterandcapabilitiesof the diary edges inGET /api/v2/survey/{surveyCode}/reach-capabilitiesGET /api/v2/workspace/{workspaceId}accepts thetypefilter to choose which element lists to return- Table responses can include an optional
diagnosticsobject 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}/variablesand/carriersnow return403when 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 (matrixListand typed axes) instead of a singlematrix. See the Migration guide
v2.1
Added
dataType,localeanddecimalsin table requests, to choose how cells are returned and formattedCARRIER_JOINTcarriers list their member carriers inidsGET /api/v2/workspace/{workspaceId}returns the saved Reach tables inreachTablesGET /api/v2/statisticsreturns adescriptionfor each statistic
v2.0
Added
POST /api/v2/reach/{surveyCode}— Calculate a Reach tableGET /api/v2/survey/{surveyCode}/reach-capabilities— Get the Reach capabilities of a surveyPOST /api/v2/table/{surveyCode}/html— Calculate a table as HTMLtargetMediain 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)