Skip to content
Product Documentation

Migration Center self-serve inbound content pipelines | Transform and Load guide

Inbound content pipelines are a set of capabilities that let you self-configure inbound content feeds from external content sources such as legacy CMS systems or third-party content providers (such as The Associated Press and Getty Images). The new feature set extends Migration Center’s existing loading capabilities to help you more quickly map external content formats from external sources to Arc XP’s internal format by generating content maps and then using our extended Migration Center APIs to transform and load content at scale.

Whether you are a customer developer, an Arc XP development partner tasked with migrating large volumes of content to Arc XP from a legacy CMS, or a client who needs to create β€˜live ingest’ pipelines of content from third-party providers, Arc XP’s inbound content pipelines provide a toolkit to help you create those integrations with more speed and reliability than writing your integrations directly to Draft API. Additionally, the toolkit is designed to be completely self-service, meaning you have control over your integration without needing input or assistance from Arc XP development staff.

Prerequisites

  • Your organization must be provisioned in Migration Center
  • Your organization must be provisioned with ANS Mapper UI
  • You should be familiar with the Migration Center API
  • You should be familiar with the respective query tooling for source document types based on the data format you are loading.

Overall process

The overall process consists of two key steps. The following sections describe these actions in detail.

  1. Create an ANS map in Migration Center for converting your source document to ANS
  2. Use the source ingestion endpoint to import data

Creating an ANS map

To bring external content into Arc XP, you must map that content to Arc XP’s native specification format, or ANS. You can use our content mapping tool in Migration Center to create this content map; however, you must know how to properly format and work with the data. Β 

Creating an ANS map in Migration Center

For full documentation on content mappings, see Creating an ANS mapping.

ANS map example

The following example shows a sample Associated Press media story with aggregated content in the source JSON and setting the ANS type to story.

Multiple source documents for a single output document

When using the ANS mapper and the Migration Center source ingestion API, you use only one source document and one mapping template at a time. This means for scenarios where you have multiple source documents generated by multiple processes that map to a single output document, you must aggregate them together in a single queryable format first before loading when applying your mapping template.

Multiple output documents in a single source document

If you have a single source that can generate multiple output types or related content, then you can upload the source document twice for each mapping template, for example, if you have a source document that generates a story and corresponding images.

It is expected that you make one story map and one image map using the same source document. This means uploading the source document twice at this time for testing in the ANS Mapper tool and for actual transformations in the Migration Center source ingestion API.

Breaking up the source document to only contain what you need for the transformation is optional. All requests to Migration Center have a maximum request size of 6 MB.

View a JSON example of an Associated Press media story with aggregated content

{
"meta": {
"products": [
{
"id": 30119,
"name": "AP Washington State News - No Weather"
},
{
"id": 30598,
"name": "AP National News Report (A Wire)"
},
{
"id": 30599,
"name": "AP Sports News (S Wire only)"
},
{
"id": 40820,
"name": "AP Washington State - Sports only"
},
{
"id": 41664,
"name": "AP Top News"
},
{
"id": 42435,
"name": "AP Top News - Sports - Stories"
},
{
"id": 100373,
"name": "MC Complete - State & National"
},
{
"id": 100502,
"name": "Member Choice Sports Option"
},
{
"id": 100518,
"name": "AP Top News Package"
}
],
"followed_topics": []
},
"item": {
"uri": "https://api.ap.org/media/v2.2/content/9168682d0e18e5fcad1baecee8b69fa3?qt=lPQ8ZbcYV-F&et=5a1aza0c0&in_my_plan=true",
"altids": {
"itemid": "9168682d0e18e5fcad1baecee8b69fa3",
"etag": "9168682d0e18e5fcad1baecee8b69fa3_5a1aza0c0",
"friendlykey": "164759759447",
"referenceid": "BBO--Home Run Derby"
},
"version": 5,
"type": "text",
"urgency": 4,
"profile": "Spot Development",
"language": "en",
"versioncreated": "2023-07-11T04:24:19Z",
"firstcreated": "2023-07-11T01:41:03Z",
"editorialrole": "FullStory",
"pubstatus": "usable",
"ednote": "Eds: UPDATES: with new lead, new photo links, video links. With AP Photos.",
"editorialtypes": ["Lead"],
"signals": ["newscontent"],
"title": "BBO--Home Run Derby",
"headline": "Vladimir Guerrero joins Vladimir Sr. as first father-son Home Run Derby winners",
"headline_extended": "Toronto’s Vladimir Guerrero Jr, joined Vladimir Sr. to become the first father-son duo to win the All-Star Home Run Derby, beating Tampa Bay’s Randy Arozarena 25-23 in the final round",
"slugline": "BC-BBO--Home Run Derby, 5th Ld-Writethru",
"description_summary": "Toronto’s Vladimir Guerrero Jr, joined Vladimir Sr. to become the first father-son duo to win the All-Star Home Run Derby, beating Tampa Bay’s Randy Arozarena 25-23 in the final round. Guerrero defeated Julio RodrΓ­guez 21-20 in the semifinals after the Mariners star hit a record 41 in the first round in front of his hometown fans. Batting against Blue Jays manager John Schneider, Guerrero was the last of the four semifinalists to swing and the first of the finalists, setting a final round record for homers to top Pete Alonso’s 23 two years ago. Vladimir Sr. won the 2007 derby.",
"bylines": [
{
"by": "By RONALD BLUM",
"title": "AP Baseball Writer"
},
{
"by": "By Jane Doe",
"title": "AP Sports Writer"
},
{
"by": "By Jack Smith",
"title": "AP Writer"
}
],
"located": "SEATTLE",
"datelinelocation": {
"city": "Seattle",
"countryareacode": "WA",
"countryareaname": "Washington",
"countrycode": "USA",
"countryname": "United States",
"geometry_geojson": {
"type": "Point",
"coordinates": [-122.33207, 47.60621]
}
},
"copyrightnotice": "Copyright 2023 The Associated Press. All rights reserved. This material may not be published, broadcast, rewritten or redistributed without permission.",
"usageterms": [
"This content is intended for editorial use only. For other uses, additional clearances may be required."
],
"keywords": ["home run derby julio rodriguez pete alonso"],
"provider": "AP",
"infosource": [
{
"name": "AP",
"type": "AP"
}
],
"person": [
{
"scheme": "http://cv.ap.org/id/",
"code": "fa25ca7f2ead3d0fb19297f56897868f",
"name": "Ken Griffey Jr.",
"creator": "Machine",
"rels": ["direct"],
"types": ["PROFESSIONAL_ATHLETE", "SPORTS_FIGURE", "PERSON"],
"teams": [
{
"code": "e8404a863bb74fc991749de07a4ff79c",
"name": "Seattle Mariners"
}
],
"relevance": 41
},
{
"scheme": "http://cv.ap.org/id/",
"code": "17be22774d004ae4944d05ebd79786fc",
"name": "Pete Alonso",
"creator": "Machine",
"rels": ["direct"],
"types": ["PROFESSIONAL_ATHLETE", "SPORTS_FIGURE", "PERSON"],
"teams": [
{
"code": "12c6685b5d2346a28a54d15b0ebaa022",
"name": "New York Mets"
}
],
"relevance": 57
},
{
"scheme": "http://cv.ap.org/id/",
"code": "a507390657d44611b998f52968488704",
"name": "John Schneider",
"creator": "Machine",
"rels": ["direct"],
"types": ["COACH", "SPORTS_FIGURE", "PERSON"],
"teams": [
{
"code": "07e1ed4bb7584a3d8c3a341f95be8df3",
"name": "Toronto Blue Jays"
}
],
"relevance": 49
},
{
"scheme": "http://cv.ap.org/id/",
"code": "07e0d9a5f1123913958de551fb66a468",
"name": "Vladimir Guerrero",
"creator": "Machine",
"rels": ["direct"],
"types": ["PROFESSIONAL_ATHLETE", "SPORTS_FIGURE", "PERSON"],
"teams": [
{
"code": "ba83eb1a77a1437bab584ff84ab2d6b3",
"name": "Baltimore Orioles"
}
],
"relevance": 76
},
{
"scheme": "http://cv.ap.org/id/",
"code": "d9b531d78a3c3d4a8e5f152ccd1bb752",
"name": "Vladimir Guerrero Jr.",
"creator": "Machine",
"rels": ["direct"],
"types": ["PROFESSIONAL_ATHLETE", "SPORTS_FIGURE", "PERSON"],
"teams": [
{
"code": "07e1ed4bb7584a3d8c3a341f95be8df3",
"name": "Toronto Blue Jays"
}
],
"relevance": 43
},
{
"scheme": "http://cv.ap.org/id/",
"code": "774de8d614d247bfb628d68446710679",
"name": "Randy Arozarena",
"creator": "Machine",
"rels": ["direct"],
"types": ["PROFESSIONAL_ATHLETE", "SPORTS_FIGURE", "PERSON"],
"teams": [
{
"code": "9018285be375430bab2167ae81d4754c",
"name": "Tampa Bay Rays"
}
],
"relevance": 66
}
],
"subject": [
{
"rels": ["category"],
"creator": "Editorial",
"code": "s",
"name": "s"
},
{
"rels": ["category"],
"creator": "Editorial",
"code": "a",
"name": "a"
},
{
"rels": ["category"],
"creator": "Editorial",
"code": "n",
"name": "n"
},
{
"scheme": "http://cv.ap.org/id/",
"code": "20d82ae87e4e100488a0d0913b2d075c",
"name": "Baseball",
"creator": "Machine",
"rels": ["direct"],
"relevance": 96
},
{
"scheme": "http://cv.ap.org/id/",
"code": "94aaa8f88c0c100489d7b9433d2f4c0e",
"name": "MLB baseball",
"creator": "Machine",
"rels": ["direct"],
"relevance": 96
},
{
"scheme": "http://cv.ap.org/id/",
"code": "a4677d70863b4012b846a1b00f5079f5",
"name": "U.S. news",
"creator": "Editorial",
"editorial_subject": "U.S. news",
"rels": ["direct"],
"relevance": 75
},
{
"scheme": "http://cv.ap.org/id/",
"code": "f25af2d07e4e100484f5df092526b43e",
"name": "General news",
"creator": "Editorial",
"editorial_subject": "General news",
"rels": ["direct"],
"relevance": 50
},
{
"scheme": "http://cv.ap.org/id/",
"code": "54df6c687df7100483dedf092526b43e",
"name": "Sports",
"creator": "Editorial",
"editorial_subject": "Sports",
"rels": ["direct"],
"relevance": 99
}
],
"organisation": [
{
"scheme": "http://cv.ap.org/id/",
"code": "cb9064a3502342e183423e4bbbd7ded3",
"name": "Chicago White Sox",
"creator": "Machine",
"rels": ["direct"],
"relevance": 32
},
{
"scheme": "http://cv.ap.org/id/",
"code": "07e1ed4bb7584a3d8c3a341f95be8df3",
"name": "Toronto Blue Jays",
"creator": "Machine",
"rels": ["direct"],
"relevance": 71
},
{
"scheme": "http://cv.ap.org/id/",
"code": "a22c87218b6f496ba912505fe4528b68",
"name": "Los Angeles Dodgers",
"creator": "Machine",
"rels": ["direct"],
"relevance": 32
},
{
"scheme": "http://cv.ap.org/id/",
"code": "5cf57e1f36d74864aa45142fd41628d7",
"name": "Los Angeles Angels",
"creator": "Machine",
"rels": ["direct"],
"relevance": 32
}
],
"audiences": [
{
"code": "82c6a4c46fa0446090a7acaf93159e4c",
"name": "Print",
"type": "AUDPLATFORM"
},
{
"code": "9add4649b53b4702ba7d9de5d4fa607a",
"name": "Online",
"type": "AUDPLATFORM"
},
{
"code": "f43adc08760d10048040e6e7a0f4673e",
"name": "National",
"type": "AUDSCOPE"
},
{
"code": "f4ecf9b0760d10048044e6e7a0f4673e",
"name": "International",
"type": "AUDSCOPE"
},
{
"code": "f5b16ea8760d10048047e6e7a0f4673e",
"name": "State",
"type": "AUDSCOPE"
},
{
"code": "661850e07d5b100481f5c076b8e3055c",
"name": "Latin America and Caribbean",
"type": "AUDGEOGRAPHY"
},
{
"code": "08a0a00882c810048942df092526b43e",
"name": "Washington",
"type": "AUDGEOGRAPHY"
},
{
"code": "661e48387d5b10048291c076b8e3055c",
"name": "United States",
"type": "AUDGEOGRAPHY"
}
],
"associations": {
"1": {
"uri": "https://api.ap.org/media/v2.2/content/369ad9b07ebc4cd5a38544b7d54d8b89?qt=lPQ8ZbcYV-F&et=0a2aza3c0&ai=9168682d0e18e5fcad1baecee8b69fa3&in_my_plan=true",
"altids": {
"itemid": "369ad9b07ebc4cd5a38544b7d54d8b89",
"etag": "369ad9b07ebc4cd5a38544b7d54d8b89_0a2aza3c0"
},
"version": 0,
"type": "picture",
"headline": "All Star Home Run Derby Baseball"
},
"2": {
"uri": "https://api.ap.org/media/v2.2/content/98a1a81dedae4db383b036c5a210e4f3?qt=lPQ8ZbcYV-F&et=1a2aza3c0&ai=9168682d0e18e5fcad1baecee8b69fa3&in_my_plan=true",
"altids": {
"itemid": "98a1a81dedae4db383b036c5a210e4f3",
"etag": "98a1a81dedae4db383b036c5a210e4f3_1a2aza3c0"
},
"version": 1,
"type": "picture",
"headline": "Home Run Derby Baseball"
},
"3": {
"uri": "https://api.ap.org/media/v2.2/content/9b23ec196ad34d389b6e9313ab67b3f4?qt=lPQ8ZbcYV-F&et=0a2aza3c0&ai=9168682d0e18e5fcad1baecee8b69fa3&in_my_plan=true",
"altids": {
"itemid": "9b23ec196ad34d389b6e9313ab67b3f4",
"etag": "9b23ec196ad34d389b6e9313ab67b3f4_0a2aza3c0"
},
"version": 0,
"type": "picture",
"headline": "Run Derby Baseball"
},
"4": {
"uri": "https://api.ap.org/media/v2.2/content/97845dc1889043e6afa6ad637881a40f?qt=lPQ8ZbcYV-F&et=0a2aza3c0&ai=9168682d0e18e5fcad1baecee8b69fa3&in_my_plan=true",
"altids": {
"itemid": "97845dc1889043e6afa6ad637881a40f",
"etag": "97845dc1889043e6afa6ad637881a40f_0a2aza3c0"
},
"version": 0,
"type": "picture",
"headline": "All Star Home Run Derby Baseball"
},
"5": {
"uri": "https://api.ap.org/media/v2.2/content/9b3c9505299b40189b6ec2cc16e4696e?qt=lPQ8ZbcYV-F&et=0a2aza3c0&ai=9168682d0e18e5fcad1baecee8b69fa3&in_my_plan=true",
"altids": {
"itemid": "9b3c9505299b40189b6ec2cc16e4696e",
"etag": "9b3c9505299b40189b6ec2cc16e4696e_0a2aza3c0"
},
"version": 0,
"type": "picture",
"headline": "All Star Home Run Derby Baseball"
},
"6": {
"uri": "https://api.ap.org/media/v2.2/content/2b2b7d82412f4d379de07a135f86efc3?qt=lPQ8ZbcYV-F&et=0a2aza3c0&ai=9168682d0e18e5fcad1baecee8b69fa3&in_my_plan=true",
"altids": {
"itemid": "2b2b7d82412f4d379de07a135f86efc3",
"etag": "2b2b7d82412f4d379de07a135f86efc3_0a2aza3c0"
},
"version": 0,
"type": "picture",
"headline": "All Star Home Run Derby Baseball"
},
"7": {
"uri": "https://api.ap.org/media/v2.2/content/e66a361abcd74f11821fe40ea69d8d73?qt=lPQ8ZbcYV-F&et=0a2aza3c0&ai=9168682d0e18e5fcad1baecee8b69fa3&in_my_plan=true",
"altids": {
"itemid": "e66a361abcd74f11821fe40ea69d8d73",
"etag": "e66a361abcd74f11821fe40ea69d8d73_0a2aza3c0"
},
"version": 0,
"type": "picture",
"headline": "All Star Home Run Derby Baseball"
},
"8": {
"uri": "https://api.ap.org/media/v2.2/content/d210cc4c27af44478734dfb6a1a8554f?qt=lPQ8ZbcYV-F&et=0a2aza3c0&ai=9168682d0e18e5fcad1baecee8b69fa3&in_my_plan=true",
"altids": {
"itemid": "d210cc4c27af44478734dfb6a1a8554f",
"etag": "d210cc4c27af44478734dfb6a1a8554f_0a2aza3c0"
},
"version": 0,
"type": "picture",
"headline": "All Star Home Run Derby Baseball"
},
"9": {
"uri": "https://api.ap.org/media/v2.2/content/7d71233a2ac34db4806ace08e1b1feac?qt=lPQ8ZbcYV-F&et=0a2aza3c0&ai=9168682d0e18e5fcad1baecee8b69fa3&in_my_plan=true",
"altids": {
"itemid": "7d71233a2ac34db4806ace08e1b1feac",
"etag": "7d71233a2ac34db4806ace08e1b1feac_0a2aza3c0"
},
"version": 0,
"type": "picture",
"headline": "All Star Home Run Derby Baseball"
},
"10": {
"uri": "https://api.ap.org/media/v2.2/content/39f6f12d86724a60bfff13c80d991062?qt=lPQ8ZbcYV-F&et=0a2aza3c0&ai=9168682d0e18e5fcad1baecee8b69fa3&in_my_plan=true",
"altids": {
"itemid": "39f6f12d86724a60bfff13c80d991062",
"etag": "39f6f12d86724a60bfff13c80d991062_0a2aza3c0"
},
"version": 0,
"type": "picture",
"headline": "All Star Home Run Derby Baseball"
},
"11": {
"uri": "https://api.ap.org/media/v2.2/content/b1d4b5bea6fe41239c4f814d2bf495ff?qt=lPQ8ZbcYV-F&et=0a2aza3c0&ai=9168682d0e18e5fcad1baecee8b69fa3&in_my_plan=true",
"altids": {
"itemid": "b1d4b5bea6fe41239c4f814d2bf495ff",
"etag": "b1d4b5bea6fe41239c4f814d2bf495ff_0a2aza3c0"
},
"version": 0,
"type": "picture",
"headline": "All Star Home Run Derby Baseball"
},
"12": {
"uri": "https://api.ap.org/media/v2.2/content/d18dad6cd0504efbb217c4b0ce250bb4?qt=lPQ8ZbcYV-F&et=0a2aza3c0&ai=9168682d0e18e5fcad1baecee8b69fa3&in_my_plan=true",
"altids": {
"itemid": "d18dad6cd0504efbb217c4b0ce250bb4",
"etag": "d18dad6cd0504efbb217c4b0ce250bb4_0a2aza3c0"
},
"version": 0,
"type": "picture",
"headline": "All Star Home Run Derby Baseball"
},
"13": {
"uri": "https://api.ap.org/media/v2.2/content/153d27e6e2a8402eba98d41df7285779?qt=lPQ8ZbcYV-F&et=0a2aza3c0&ai=9168682d0e18e5fcad1baecee8b69fa3&in_my_plan=true",
"altids": {
"itemid": "153d27e6e2a8402eba98d41df7285779",
"etag": "153d27e6e2a8402eba98d41df7285779_0a2aza3c0"
},
"version": 0,
"type": "picture",
"headline": "All Star Home Run Derby Baseball"
}
},
"renditions": {
"nitf": {
"title": "NITF Story Download",
"rel": "Story",
"format": "IIM",
"type": "text",
"mimetype": "text/xml",
"fileextension": "xml",
"words": 764,
"contentid": "41ead9df1a60bd366f333dfa735fa842",
"href": "https://api.ap.org/media/v2.2/content/9168682d0e18e5fcad1baecee8b69fa3.5/download?type=text&format=NITF&rid=41ead9df1a60bd366f333dfa735fa842&cid=0&fid=55ec7f6e6d6b49c78ba673ab475cd88e&trf=a0484&qt=lPQ8ZbcYV-F&dt=-OKsxE1bQD&et=5a1aza0c0",
"mediafilterid": "2",
"content": "<nitf xmlns=\"http://iptc.org/std/NITF/2006-10-18/\" version=\"-//IPTC//DTD NITF 3.4//EN\" change.date=\"October 18, 2006\" change.time=\"19:30\">\n <head>\n <docdata>\n <doc-id regsrc=\"AP\"/>\n <date.issue norm=\"20230711T042419Z\"/>\n <ed-msg info=\"Eds: UPDATES: with new lead, new photo links, video links. With AP Photos.\"/>\n <doc.copyright holder=\"AP\" year=\"2023\"/>\n <identified-content>\n <classifier type=\"apcategorycode\" value=\"s\"/>\n <classifier type=\"apcategorycode\" value=\"a\"/>\n <classifier type=\"apcategorycode\" value=\"n\"/>\n </identified-content>\n </docdata>\n </head>\n <body>Vladimir Guerrero joins Vladimir Sr. as first father-son Home Run Derby winnersBy RONALD BLUMAP Baseball WriterThe Associated PressSEATTLEToronto’s Vladimir Guerrero Jr, joined Vladimir Sr. to become the first father-son duo to win the All-Star Home Run Derby, beating Tampa Bay’s Randy Arozarena 25-23 in the final round. Guerrero defeated Julio RodrΓ­guez 21-20 in the semifinals after the Mariners star hit a record 41 in the first round in front of his hometown fans. Batting against Blue Jays manager John Schneider, Guerrero was the last of the four semifinalists to swing and the first of the finalists, setting a final round record for homers to top Pete Alonso’s 23 two years ago. Vladimir Sr. won the 2007 derby. SEATTLE (AP) β€” Of course a Junior had to do something special in Seattle. Vladimir Guerrero Jr. won the All-Star Home Run Derby on Monday night, matching Vladimir Sr.'s 2007 title to become the first father-son duo to accomplish the feat. As far as who might win a head-to-head swing-off, well, that depends. β€œIt's kind of difficult right now,” the Toronto Blue Jays star said with a wide grin, speaking through a translator. β€œWith the time, with the minutes, I'll win. If it's by outs, he'll win.” In a ballpark made famous by the Mariners' Ken Griffey Jr. a generation earlier, Guerrero beat Tampa Bay's Randy Arozarena 25-23 in the final round. He was 8 when his father won the crown in San Francisco. β€œI don’t remember much about 2007,\" Vladimir Jr. said. β€œI guess I was too young.” Guerrero totaled 5 1/2 miles of homers β€” 29,390 feet to be exact. He defeated Julio RodrΓ­guez 21-20 in the semifinals after the Mariners star hit a record 41 in the first round in front of his hometown fans. Batting against Blue Jays manager John Schneider, Guerrero was the last semifinalist to swing and the first finalist, setting a final round record for homers to top the mark Pete Alonso set when he beat Guerrero 23-22 in 2019. With Guerrero Jr. catching his breath while watching, Arozarena hit against Tampa Bay field coordinator Tomas Francisco. Arozarena had 21 homers in his initial 2 minutes. He had 23 with 7 seconds left in his automatic 30 seconds of bonus time before lining and popping up on his final four swings. Guerrero had 1 minute of bonus time, earning an additional 30 seconds because he twice reached 440 feet. β€œObviously, the power that he has was incredible,” Arozarena said through a translator. β€œFor me, I felt good going into that round. But also he was able to get a minute of bonus time. I only had the 30 seconds of bonus time.” Vladimir Guerrero Sr. won the 2007 derby while with the Los Angeles Angels, beating the Blue Jays’ Alex Rios 3-2 in the final. Arozarena had the most overall homers over the three rounds, 82 to Guerrero's 72, and the most distance at 33,077 feet. Arozarena overcame Luis Robert of the Chicago White Sox 35-22 in the semifinals. Robert hit the longest drive of the night, a 484-foot shot to left in the second round. That topped the high of 476 feet by Barry Bonds in the 2001 derby in Seattle. Trying to become the youngest Derby winner at age 22, RodrΓ­guez knocked out Alonso, a two-time champion who hit 21. RodrΓ­guez beat Corey Seager 32-24 in the first round last year at Dodger Stadium, then knocked out Alonso 31-23 before losing to Juan Soto 19-18 in the final. Arozarena beat Texas’ Adolis GarcΓ­a 24-17 in the opening pairing before a crowd of 46,952 at T-Mobile Park. GarcΓ­a is the godfather to Arozarena’s daughter, and the two jumped into each other’s arms during warmups. Robert knocked out Baltimore’s Adley Rutschman 28-27 in the opening round. Rutschman hit 21 left-handed, and the switch hitter then turned around to the right side and hit six more right-handed during a 30-second bonus round. From Portland, Oregon, Rutschman grew up attending Mariners games. Guerrero, back for the first time in four years, defeated the Los Angeles Dodgers’ Mookie Betts 26-11 in the first round. Four years ago at Cleveland, Guerrero hit 29 in the first round and 40 in the second, then lost to Alonso in the final. Alonso was trying for his third title in four years. Griffey Jr. is the only three-time winner, taking the title in 1994, ’98 and β€˜99. Guerrero Sr. was a nine-time All-Star but never won a World Series. He was inducted into the Hall of Fame in 2018. Guerrero Jr. is a three-time All-Star and was MVP of the game two years ago in Denver. What's in the future? A World Series ring? Joining dad in the Hall? β€œI’m a little bit too young to think about that right now,” he said. β€œWhen I get there, then I’ll think about it, I’ll see if I match my dad or was better than my dad or not.” ___ AP MLB: https://apnews.com/hub/MLB and https://twitter.com/AP_Sports <body.content>\n <block>\n <p>SEATTLE (AP) β€” Of course a Junior had to do something special in Seattle.</p>\n <p>\n <a href=\"https://www.mlb.com/video/vlad-guerrero-jr-wins-2023-derby?partnerId=web_video-playback-page_video-share\">Vladimir Guerrero Jr.</a> won the All-Star Home Run Derby on Monday night, matching Vladimir Sr.'s 2007 title to become the first father-son duo to accomplish the feat.</p>\n <p>As far as who might win a head-to-head swing-off, well, that depends.</p>\n <p>β€œIt's kind of difficult right now,” the Toronto Blue Jays star said with a wide grin, speaking through a translator. β€œWith the time, with the minutes, I'll win. If it's by outs, he'll win.”</p>\n <p>In a ballpark made famous by the Mariners' Ken Griffey Jr. a generation earlier, Guerrero beat <a href=\"https://www.mlb.com/video/arozarena-s-23-homers-in-finals?partnerId=web_video-playback-page_video-share\">Tampa Bay's Randy Arozarena</a> 25-23 in the final round. He was 8 when his father won the crown in San Francisco.</p>\n <p>β€œI don’t remember much about 2007,\" Vladimir Jr. said. β€œI guess I was too young.”</p>\n <p>Guerrero totaled 5 1/2 miles of homers β€” 29,390 feet to be exact. He defeated Julio RodrΓ­guez 21-20 in the semifinals after the Mariners star hit a record 41 in the first round in front of his hometown fans. </p>\n <p>Batting against Blue Jays manager John Schneider, Guerrero was the last semifinalist to swing and the first finalist, setting a final round record for homers to top the mark Pete Alonso set when he beat Guerrero 23-22 in 2019.</p>\n <p>With Guerrero Jr. catching his breath while watching, Arozarena hit against Tampa Bay field coordinator Tomas Francisco. Arozarena had 21 homers in his initial 2 minutes. <a href=\"https://www.mlb.com/video/arozarena-s-23rd-hr-of-the-finals?partnerId=web_video-playback-page_video-share\">He had 23 with 7 seconds left in his automatic 30 seconds of bonus time before lining and popping up on his final four swings</a>.\n </p>\n <p>Guerrero had 1 minute of bonus time, earning an additional 30 seconds because he twice reached 440 feet.</p>\n <p>β€œObviously, the power that he has was incredible,” Arozarena said through a translator. β€œFor me, I felt good going into that round. But also he was able to get a minute of bonus time. I only had the 30 seconds of bonus time.”</p>\n <p>Vladimir Guerrero Sr. won the 2007 derby while with the Los Angeles Angels, beating the Blue Jays’ Alex Rios 3-2 in the final.</p>\n <p>Arozarena had the most overall homers over the three rounds, 82 to Guerrero's 72, and the most distance at 33,077 feet. Arozarena overcame Luis Robert of the Chicago White Sox 35-22 in the semifinals. Robert hit the longest drive of the night, a 484-foot shot to left in the second round. That topped the high of 476 feet by Barry Bonds in the 2001 derby in Seattle.</p>\n <p>Trying to become the youngest Derby winner at age 22, RodrΓ­guez knocked out Alonso, a two-time champion who hit 21. RodrΓ­guez beat Corey Seager 32-24 in the first round last year at Dodger Stadium, then knocked out Alonso 31-23 before losing to Juan Soto 19-18 in the final.</p>\n <p>Arozarena beat Texas’ Adolis GarcΓ­a 24-17 in the opening pairing before a crowd of 46,952 at T-Mobile Park. GarcΓ­a is the godfather to Arozarena’s daughter, and the two jumped into each other’s arms during warmups.</p>\n <p>\n <a href=\"https://www.mlb.com/video/robert-jr-s-28-round-1-homers?partnerId=web_video-playback-page_video-share\">Robert knocked out Baltimore’s Adley Rutschman 28-27</a> in the opening round. Rutschman hit 21 left-handed, and <a href=\"https://apnews.com/article/adley-rutschman-home-run-derby-de7290bb10aa7046e3b5928831da83a2\">the switch hitter</a> then <a href=\"https://www.mlb.com/video/adley-rutschman-switches-sides?partnerId=web_video-playback-page_video-share\">turned around to the right side and hit six more right-handed</a> during a 30-second bonus round. From Portland, Oregon, Rutschman grew up attending Mariners games.</p>\n <p>Guerrero, back for the first time in four years, <a href=\"https://www.mlb.com/video/guerrero-jr-s-26-round-1-homers?partnerId=web_video-playback-page_video-share\">defeated the Los Angeles Dodgers’ Mookie Betts 26-11</a> in the first round. Four years ago at Cleveland, <a href=\"https://apnews.com/article/56dbc7f1203b444fb1fb37d3385d84e9\">Guerrero hit 29 in the first round and 40 in the second, then lost to Alonso in the final</a>. \n </p>\n <p>Alonso was trying for his third title in four years. Griffey Jr. is the only three-time winner, taking the title in 1994, ’98 and β€˜99.</p>\n <p>Guerrero Sr. was a nine-time All-Star but never won a World Series. He was inducted into the Hall of Fame in 2018.</p>\n <p>Guerrero Jr. is a three-time All-Star and was MVP of the game two years ago in Denver. What's in the future? A World Series ring? Joining dad in the Hall?</p>\n <p>β€œI’m a little bit too young to think about that right now,” he said. β€œWhen I get there, then I’ll think about it, I’ll see if I match my dad or was better than my dad or not.” </p>\n <p>___</p>\n <p>AP MLB: <a href=\"https://apnews.com/hub/MLB\">https://apnews.com/hub/MLB</a> and <a href=\"https://twitter.com/AP_Sports\">https://twitter.com/AP_Sports</a>\n </p>\n </block>\n </body.content>\n</body>\n</nitf>"
}
},
"textformat": "bx",
"links": [
{
"href": "https://apnews.com/article/home-run-derby-julio-rodriguez-pete-alonso-9168682d0e18e5fcad1baecee8b69fa3",
"rel": "canonical"
}
]
}
}

Validating your ANS map

After you create an ANS map in Migration Center, validate the ANS map to confirm it is not generating any errors. See Validating a mapping.

When the ANS is validated, save the map by clicking Save.

View the corresponding mapping template for generating the ANS document

{
"id": "1699672679252",
"name": "AP Embedded Story",
"documentType": "json",
"mappings": [
{
"targetPath": "ANS._id",
"conditions": [
true,
"item.renditions.nitf.contentid != null"
],
"actions": [
{
"type": "def",
"query": "item.renditions.nitf.contentid"
},
{
"type": "fn",
"name": "generateArcHash",
"params": [
{
"hash": "staging"
}
]
}
]
},
{
"targetPath": "ANS.type",
"actions": [
{
"type": "def",
"set": "story"
}
]
},
{
"targetPath": "ANS.version",
"actions": [
{
"type": "def",
"set": "0.10.9"
}
]
},
{
"targetPath": "ANS.canonical_website",
"actions": [
{
"type": "def",
"set": "staging"
}
]
},
{
"targetPath": "ANS.comments",
"actions": [
{
"type": "def",
"set": {
"allow_comments": false,
"display_comments": false,
"moderation_required": false
}
}
]
},
{
"targetPath": "ANS.content_restrictions",
"actions": [
{
"type": "def",
"set": {
"content_code": "ap_wires_content",
"embargo": {
"active": true
}
}
}
]
},
{
"targetPath": "ANS.copyright",
"actions": [
{
"type": "def",
"query": "item.copyrightnotice"
}
]
},
{
"targetPath": "ANS.credits.by",
"actions": [
{
"type": "def",
"query": "item.bylines"
},
{
"type": "fn",
"name": "map",
"params": [
{
"mappings": [
{
"targetPath": "type",
"actions": [
{
"type": "def",
"set": "author"
}
]
},
{
"targetPath": "name",
"actions": [
{
"type": "def",
"query": "by"
},
{
"type": "fn",
"name": "replaceText",
"params": [
{
"pattern": "By ",
"replacement": ""
}
]
}
]
},
{
"targetPath": "org",
"actions": [
{
"type": "def",
"query": "title"
}
]
},
{
"targetPath": "affiliation",
"actions": [
{
"type": "def",
"query": "title"
}
]
}
]
}
]
}
]
},
{
"targetPath": "ANS.description.basic",
"actions": [
{
"type": "def",
"query": "item.headline_extended"
}
]
},
{
"targetPath": "ANS.display_date",
"actions": [
{
"type": "def",
"query": "item.versioncreated"
},
{
"type": "fn",
"name": "toDate"
}
]
},
{
"targetPath": "ANS.distributor.mode",
"actions": [
{
"type": "def",
"set": "reference"
}
]
},
{
"targetPath": "ANS.distributor.reference_id",
"actions": [
{
"type": "def",
"set": "4e36c6d6-f9c9-46f3-9b1e-218007f5690d"
}
]
},
{
"targetPath": "ANS.headlines.basic",
"actions": [
{
"type": "def",
"query": "item.headline"
}
]
},
{
"targetPath": "ANS.language",
"actions": [
{
"type": "def",
"query": "item.language"
}
]
},
{
"targetPath": "ANS.location",
"actions": [
{
"type": "def",
"query": "item.located"
}
]
},
{
"targetPath": "ANS.planning.budget_line",
"actions": [
{
"type": "def",
"query": "item.slugline"
}
]
},
{
"targetPath": "ANS.planning.internal_note",
"actions": [
{
"type": "def",
"query": "item.ednote"
}
]
},
{
"targetPath": "ANS.planning.scheduling.planned_publish_date",
"actions": [
{
"type": "def",
"query": "item.versioncreated"
},
{
"type": "fn",
"name": "toDate"
}
]
},
{
"targetPath": "ANS.planning.scheduling.will_have_image",
"actions": [
{
"type": "def",
"set": true
}
]
},
{
"targetPath": "ANS.slug",
"actions": [
{
"type": "def",
"query": "item.slugline"
}
]
},
{
"targetPath": "ANS.source.source_id",
"actions": [
{
"type": "def",
"query": "item.altids.itemid"
}
]
},
{
"targetPath": "ANS.source.system",
"actions": [
{
"type": "def",
"set": "ArcXP Exchange"
}
]
},
{
"targetPath": "ANS.status",
"actions": [
{
"type": "def",
"query": "item.pubstatus"
}
]
},
{
"targetPath": "ANS.subheadlines.basic",
"actions": [
{
"type": "def",
"query": "item.headline_extended"
}
]
},
{
"targetPath": "ANS.subtype",
"actions": [
{
"type": "def",
"set": "ap-wires-story"
}
]
},
{
"targetPath": "ANS.syndication",
"actions": [
{
"type": "def",
"set": {
"external_distribution": false,
"search": false
}
}
]
},
{
"targetPath": "ANS.tracking",
"actions": [
{
"type": "def",
"set": {
"noindex_nofollow": false
}
}
]
},
{
"targetPath": "ANS.workflow",
"actions": [
{
"type": "def",
"set": {
"status_code": 1,
"note": "Associated Press wires content"
}
}
]
},
{
"targetPath": "ANS.additional_properties.originalUrl",
"actions": [
{
"type": "def",
"query": "item.links[0].href"
}
]
},
{
"targetPath": "ANS.additional_properties.sourceRevision",
"actions": [
{
"type": "def",
"query": "item.altids.etag"
}
]
},
{
"targetPath": "ANS.content_elements",
"actions": [
{
"type": "def",
"query": "item.renditions.nitf.content"
},
{
"type": "fn",
"name": "search",
"params": [
{
"search": "/*[name() = 'nitf']/*[name() = 'body']/*[name() = 'body.content']/child::node()",
"type": "xml"
}
]
},
{
"type": "fn",
"name": "nitfToANS"
}
]
},
{
"targetPath": "ANS.promo_items.basic",
"actions": [
{
"type": "def",
"query": "item.associations"
},
{
"type": "fn",
"name": "objectValues"
},
{
"type": "fn",
"name": "first"
},
{
"type": "fn",
"name": "map",
"params": [
{
"mappings": [
{
"targetPath": "type",
"actions": [
{
"type": "def",
"set": "reference"
}
]
},
{
"targetPath": "referent.type",
"actions": [
{
"type": "def",
"set": "image"
}
]
},
{
"targetPath": "referent.id",
"actions": [
{
"type": "def",
"query": "altids.itemid"
},
{
"type": "fn",
"name": "generateArcHash",
"params": [
{
"hash": "staging"
}
]
}
]
}
]
}
]
}
]
},
{
"targetPath": "ANS.related_content.basic",
"actions": [
{
"type": "def",
"query": "item.associations"
},
{
"type": "fn",
"name": "objectValues"
},
{
"type": "fn",
"name": "map",
"params": [
{
"mappings": [
{
"targetPath": "type",
"actions": [
{
"type": "def",
"set": "reference"
}
]
},
{
"targetPath": "referent.type",
"actions": [
{
"type": "def",
"set": "image"
}
]
},
{
"targetPath": "referent.id",
"actions": [
{
"type": "def",
"query": "altids.itemid"
},
{
"type": "fn",
"name": "generateArcHash",
"params": [
{
"hash": "staging"
}
]
}
]
}
]
}
]
}
]
},
{
"targetPath": "circulations",
"actions": [
{
"type": "def",
"set": [
{
"document_id": null,
"website_id": "staging",
"website_sections": [
{
"type": "reference",
"referent": {
"type": "section",
"website": "staging",
"id": "/dogs"
}
}
],
"website_primary_section": {
"type": "reference",
"referent": {
"type": "section",
"website": "staging",
"id": "/dogs"
}
}
}
]
},
{
"type": "fn",
"name": "map",
"params": [
{
"mappings": [
{
"targetPath": "website_id",
"actions": [
{
"type": "def",
"query": "website_id"
}
]
},
{
"targetPath": "website_sections",
"actions": [
{
"type": "def",
"query": "website_sections"
}
]
},
{
"targetPath": "website_primary_section",
"actions": [
{
"type": "def",
"query": "website_primary_section"
}
]
},
{
"targetPath": "document_id",
"actions": [
{
"type": "def",
"query": "item.renditions.nitf.contentid"
},
{
"type": "fn",
"name": "generateArcHash",
"params": [
{
"hash": "staging"
}
]
}
]
}
]
}
]
}
]
}
]
}

Your generated ANS should translate to the following:

View generated ANS based on the previous source and mapping template

{
"ANS": {
"_id": "3VRQ4G6HNVKRRCPJ2ATWP3IJIU",
"type": "story",
"version": "0.10.9",
"canonical_website": "staging",
"comments": {
"allow_comments": false,
"display_comments": false,
"moderation_required": false
},
"content_restrictions": {
"content_code": "ap_wires_content",
"embargo": {
"active": true
}
},
"copyright": "Copyright 2023 The Associated Press. All rights reserved. This material may not be published, broadcast, rewritten or redistributed without permission.",
"credits": {
"by": [
{
"type": "author",
"name": "RONALD BLUM",
"org": "AP Baseball Writer",
"affiliation": "AP Baseball Writer"
},
{
"type": "author",
"name": "Jane Doe",
"org": "AP Sports Writer",
"affiliation": "AP Sports Writer"
},
{
"type": "author",
"name": "Jack Smith",
"org": "AP Writer",
"affiliation": "AP Writer"
}
]
},
"description": {
"basic": "Toronto’s Vladimir Guerrero Jr, joined Vladimir Sr. to become the first father-son duo to win the All-Star Home Run Derby, beating Tampa Bay’s Randy Arozarena 25-23 in the final round"
},
"display_date": "2023-07-11T04:24:19.000Z",
"distributor": {
"mode": "reference",
"reference_id": "4e36c6d6-f9c9-46f3-9b1e-218007f5690d"
},
"headlines": {
"basic": "Vladimir Guerrero joins Vladimir Sr. as first father-son Home Run Derby winners"
},
"language": "en",
"location": "SEATTLE",
"planning": {
"budget_line": "BC-BBO--Home Run Derby, 5th Ld-Writethru",
"internal_note": "Eds: UPDATES: with new lead, new photo links, video links. With AP Photos.",
"scheduling": {
"planned_publish_date": "2023-07-11T04:24:19.000Z",
"will_have_image": true
}
},
"slug": "BC-BBO--Home Run Derby, 5th Ld-Writethru",
"source": {
"source_id": "9168682d0e18e5fcad1baecee8b69fa3",
"system": "ArcXP Exchange"
},
"status": "usable",
"subheadlines": {
"basic": "Toronto’s Vladimir Guerrero Jr, joined Vladimir Sr. to become the first father-son duo to win the All-Star Home Run Derby, beating Tampa Bay’s Randy Arozarena 25-23 in the final round"
},
"subtype": "ap-wires-story",
"syndication": {
"external_distribution": false,
"search": false
},
"tracking": {
"noindex_nofollow": false
},
"workflow": {
"status_code": 1,
"note": "Associated Press wires content"
},
"additional_properties": {
"originalUrl": "https://apnews.com/article/home-run-derby-julio-rodriguez-pete-alonso-9168682d0e18e5fcad1baecee8b69fa3",
"sourceRevision": "9168682d0e18e5fcad1baecee8b69fa3_5a1aza0c0"
},
"content_elements": [
{
"type": "text",
"content": "SEATTLE (AP) β€” Of course a Junior had to do something special in Seattle.",
"additional_properties": {}
},
{
"type": "text",
"content": "\n <a href=\"https://www.mlb.com/video/vlad-guerrero-jr-wins-2023-derby?partnerId=web_video-playback-page_video-share\">Vladimir Guerrero Jr.</a> won the All-Star Home Run Derby on Monday night, matching Vladimir Sr.'s 2007 title to become the first father-son duo to accomplish the feat.",
"additional_properties": {}
},
{
"type": "text",
"content": "As far as who might win a head-to-head swing-off, well, that depends.",
"additional_properties": {}
},
{
"type": "text",
"content": "β€œIt's kind of difficult right now,” the Toronto Blue Jays star said with a wide grin, speaking through a translator. β€œWith the time, with the minutes, I'll win. If it's by outs, he'll win.”",
"additional_properties": {}
},
{
"type": "text",
"content": "In a ballpark made famous by the Mariners' Ken Griffey Jr. a generation earlier, Guerrero beat <a href=\"https://www.mlb.com/video/arozarena-s-23-homers-in-finals?partnerId=web_video-playback-page_video-share\">Tampa Bay's Randy Arozarena</a> 25-23 in the final round. He was 8 when his father won the crown in San Francisco.",
"additional_properties": {}
},
{
"type": "text",
"content": "β€œI dont remember much about 2007,\" Vladimir Jr. said. β€œI guess I was too young.”",
"additional_properties": {}
},
{
"type": "text",
"content": "Guerrero totaled 5 1/2 miles of homers β€” 29,390 feet to be exact. He defeated Julio RodrΓ­guez 21-20 in the semifinals after the Mariners star hit a record 41 in the first round in front of his hometown fans. ",
"additional_properties": {}
},
{
"type": "text",
"content": "Batting against Blue Jays manager John Schneider, Guerrero was the last semifinalist to swing and the first finalist, setting a final round record for homers to top the mark Pete Alonso set when he beat Guerrero 23-22 in 2019.",
"additional_properties": {}
},
{
"type": "text",
"content": "With Guerrero Jr. catching his breath while watching, Arozarena hit against Tampa Bay field coordinator Tomas Francisco. Arozarena had 21 homers in his initial 2 minutes. <a href=\"https://www.mlb.com/video/arozarena-s-23rd-hr-of-the-finals?partnerId=web_video-playback-page_video-share\">He had 23 with 7 seconds left in his automatic 30 seconds of bonus time before lining and popping up on his final four swings</a>.\n ",
"additional_properties": {}
},
{
"type": "text",
"content": "Guerrero had 1 minute of bonus time, earning an additional 30 seconds because he twice reached 440 feet.",
"additional_properties": {}
},
{
"type": "text",
"content": "β€œObviously, the power that he has was incredible,” Arozarena said through a translator. β€œFor me, I felt good going into that round. But also he was able to get a minute of bonus time. I only had the 30 seconds of bonus time.”",
"additional_properties": {}
},
{
"type": "text",
"content": "Vladimir Guerrero Sr. won the 2007 derby while with the Los Angeles Angels, beating the Blue Jays’ Alex Rios 3-2 in the final.",
"additional_properties": {}
},
{
"type": "text",
"content": "Arozarena had the most overall homers over the three rounds, 82 to Guerrero's 72, and the most distance at 33,077 feet. Arozarena overcame Luis Robert of the Chicago White Sox 35-22 in the semifinals. Robert hit the longest drive of the night, a 484-foot shot to left in the second round. That topped the high of 476 feet by Barry Bonds in the 2001 derby in Seattle.",
"additional_properties": {}
},
{
"type": "text",
"content": "Trying to become the youngest Derby winner at age 22, RodrΓ­guez knocked out Alonso, a two-time champion who hit 21. RodrΓ­guez beat Corey Seager 32-24 in the first round last year at Dodger Stadium, then knocked out Alonso 31-23 before losing to Juan Soto 19-18 in the final.",
"additional_properties": {}
},
{
"type": "text",
"content": "Arozarena beat Texas’ Adolis GarcΓ­a 24-17 in the opening pairing before a crowd of 46,952 at T-Mobile Park. GarcΓ­a is the godfather to Arozarena’s daughter, and the two jumped into each other’s arms during warmups.",
"additional_properties": {}
},
{
"type": "text",
"content": "\n <a href=\"https://www.mlb.com/video/robert-jr-s-28-round-1-homers?partnerId=web_video-playback-page_video-share\">Robert knocked out Baltimore’s Adley Rutschman 28-27</a> in the opening round. Rutschman hit 21 left-handed, and <a href=\"https://apnews.com/article/adley-rutschman-home-run-derby-de7290bb10aa7046e3b5928831da83a2\">the switch hitter</a> then <a href=\"https://www.mlb.com/video/adley-rutschman-switches-sides?partnerId=web_video-playback-page_video-share\">turned around to the right side and hit six more right-handed</a> during a 30-second bonus round. From Portland, Oregon, Rutschman grew up attending Mariners games.",
"additional_properties": {}
},
{
"type": "text",
"content": "Guerrero, back for the first time in four years, <a href=\"https://www.mlb.com/video/guerrero-jr-s-26-round-1-homers?partnerId=web_video-playback-page_video-share\">defeated the Los Angeles Dodgers’ Mookie Betts 26-11</a> in the first round. Four years ago at Cleveland, <a href=\"https://apnews.com/article/56dbc7f1203b444fb1fb37d3385d84e9\">Guerrero hit 29 in the first round and 40 in the second, then lost to Alonso in the final</a>. \n ",
"additional_properties": {}
},
{
"type": "text",
"content": "Alonso was trying for his third title in four years. Griffey Jr. is the only three-time winner, taking the title in 1994, ’98 and β€˜99.",
"additional_properties": {}
},
{
"type": "text",
"content": "Guerrero Sr. was a nine-time All-Star but never won a World Series. He was inducted into the Hall of Fame in 2018.",
"additional_properties": {}
},
{
"type": "text",
"content": "Guerrero Jr. is a three-time All-Star and was MVP of the game two years ago in Denver. What's in the future? A World Series ring? Joining dad in the Hall?",
"additional_properties": {}
},
{
"type": "text",
"content": "β€œI’m a little bit too young to think about that right now,” he said. β€œWhen I get there, then I’ll think about it, I’ll see if I match my dad or was better than my dad or not.” ",
"additional_properties": {}
},
{
"type": "text",
"content": "___",
"additional_properties": {}
},
{
"type": "text",
"content": "AP MLB: <a href=\"https://apnews.com/hub/MLB\">https://apnews.com/hub/MLB</a> and <a href=\"https://twitter.com/AP_Sports\">https://twitter.com/AP_Sports</a>\n ",
"additional_properties": {}
}
],
"promo_items": {
"basic": {
"type": "reference",
"referent": {
"type": "image",
"id": "K2AI7KSAVBPJXK5DZUXTRIFKYY"
}
}
},
"related_content": {
"basic": [
{
"type": "reference",
"referent": {
"type": "image",
"id": "K2AI7KSAVBPJXK5DZUXTRIFKYY"
}
},
{
"type": "reference",
"referent": {
"type": "image",
"id": "AJCFESCHKZIWLLALRCI34VG7JM"
}
},
{
"type": "reference",
"referent": {
"type": "image",
"id": "BCGNB6DKJZMTPDYTLZSUHPWYA4"
}
},
{
"type": "reference",
"referent": {
"type": "image",
"id": "T5NVSWBBNZOSRANFHY6PX63C74"
}
},
{
"type": "reference",
"referent": {
"type": "image",
"id": "TVNWJUMPHZPAJOBRVCVPIUMDOQ"
}
},
{
"type": "reference",
"referent": {
"type": "image",
"id": "ZKBNWYCVEFLJFEKDVRCVZKFSGU"
}
},
{
"type": "reference",
"referent": {
"type": "image",
"id": "J7GK3FW4QVLERNGKS6X6KADIPY"
}
},
{
"type": "reference",
"referent": {
"type": "image",
"id": "LY2U7HZJGVLKLDU5LZFULLHHUE"
}
},
{
"type": "reference",
"referent": {
"type": "image",
"id": "XJH2KUEIKNK6DGFTKKPYU2H7XU"
}
},
{
"type": "reference",
"referent": {
"type": "image",
"id": "F5TA4KOG6ZOMJKPRVNROQ5LNZQ"
}
},
{
"type": "reference",
"referent": {
"type": "image",
"id": "OJGOKI7M2NMYRL3SQJGH3UHDYI"
}
},
{
"type": "reference",
"referent": {
"type": "image",
"id": "GHDUL5LENZMXTJPLMWU7YBJNIM"
}
},
{
"type": "reference",
"referent": {
"type": "image",
"id": "CUABFXTXWRMLZPW4OKBOAPYJKU"
}
}
]
}
},
"circulations": [
{
"website_id": "staging",
"website_sections": [
{
"type": "reference",
"referent": {
"type": "section",
"website": "staging",
"id": "/dogs"
}
}
],
"website_primary_section": {
"type": "reference",
"referent": {
"type": "section",
"website": "staging",
"id": "/dogs"
}
},
"document_id": "3VRQ4G6HNVKRRCPJ2ATWP3IJIU"
}
]
}

Retrieving the mapID

After testing and verifying that your map transforms as expected, you must retrieve the mapID. You use the mapID when when applying the mapping to source data to create ANS.

You can retrieve the mapID in one of two ways: from the ANS map or from the application URL.

  • ANS map - the mapID is available in your ANS map, as show in the following example.
    ANS Map
  • application URL - when you have your ANS map open, the URL displays the mapid.
    Application URL

Use the source ingestion endpoint to load source documents

After you create your ANS map, you can call the POST /migrations/v3/content/source endpoint in the Migration Center API to load a document.

To transform your source content, you must pass the sourceContent along with the sourceAdditionalProperties in the body of the request, the result of this action is as follows:

  1. Migration Center saves your source information and submits it for transformation.Β 
  2. After your source information is transformed, Migration Center saves the output for reference when using the details endpoint. Your map must generate an output that matches Migration Center’s [Post] ANS ingestion endpoint to avoid a transform failure. See API documentation for endpoint /migrations/v3/content/ans.
  3. After your information is saved, it’s forwarded through Migration Center’s loading system into Arc XP.
  4. When it’s loaded, you have valid ANS in the Arc XP application for the generated ANS type.

Example of source additional properties:

{
"sourceContent": <AP Media Source Content>,
"sourceAdditionalProperties": {
"transform": {
"mapId": "${Your Map ID}"
}
}
}

After you submit the source document, you can track status with the migration/v3/report/detail endpoint to verify that you successfully submitted.

When you submit content, your content cycles through the following status: Pending, Queued, Processing, [ANS-specific type statuses]. The process may move quickly, so you might not see all statuses. To see the latest status, refresh the API call.

Creating mapping templates

The mapping templates purpose is to allow a user to locate/query fields in a given source document and assign them to their respective location in Arc’s ANS schema as output.

  1. When making mapping templates you define a targetPath that defines where a query will assign values.Β 
  2. Then, you define what your initial value is. This can be either a static value or a query that reads the source document via the def action.
    1. Any JSON value is valid for assigning to a targetPath.
  3. Then, optionally, if want to manipulate your value or coerce it into a specific format or value, you can specify actions or functions (fn) by using an action configuration.Β 
    1. Actions are performed 1 at a time and in the order specified in the JSON array.

Below is the documentation about transformation actions that are available when utilizing the mapping schema to transform content.

Mapping Schema

The mapping schema uses a configurable format that can process either JSON (via JMESPath) or XML (via XPath) documents for specifying actions to apply to your target mappings and generate a transformed output.

type MappingTemplate = {
documentType: string; // source document type: "json" | "xml"
environment?: {
xml: {
namespaces: {
[k: string]: string;
};
};
};
mappings: [ // Mapping[]
{
targetPath: string; // ANS.type
strict?: boolean; // default false
conditions?: (string | boolean)[];
actions: [ // Action[]
{
type: "def";
set: "story";
},
{
type: "fn";
name: "toUpperCase";
},
];
},
];
};
// result => // { ANS: { type: 'STORY' } }

Properties of a mapping

  • targetPathΒ -> The path you want to create in the target ANS output JSON.
  • actionsΒ -> The list of actions you want to run to modify or create a value at theΒ targetPath.
  • conditionsΒ -> static boolean values or string queries to run to decide whether to map a value.
  • strictΒ -> Primarily for debugging, but useful to force errors on mapping. Errors by default will be silent and will result in undefined mappings.

As you work through mappings, you will see that a mapping is likely needed for each property of a JSON or XML document to map that field to the target JSON document.

Action types

Definition actions

Definitions are simply actions that define the key path and value on top of target output with a static valueΒ setΒ or based on aΒ query. So, setting the valueΒ 2Β onΒ "targetPath": "id"Β creates an objectΒ { "id": 2 }.

type DefineAction = {
type: "def";
set?: string;
query?: string | { value: string; type: "json" | "xml" };
};

Function actions

type FunctionAction = {
type: "fn";
name: string;
params: [];
};

When applying functions to targets, be aware that you are operating on an underlying value that was previously generated. This means that when reading the documentation, wherever it saysΒ targetΒ it is referring to the underlying target implicitly, not something that must be passed in.

TheΒ paramsΒ are only required when a function calls out that there are parameters to pass in.

As a general note, your parameter mappings must be in an array format, unless otherwise specified by the action definition.

For functions that operate on scalar values, the respective function will call out that it operates on a single scalar value or a list of scalar values. This is a feature provided to avoid situations where you would need to use theΒ mapΒ function to iterate over the scope of a single item.

Supported functions

Arrays

  • concat
  • filter
  • first
  • flat
  • join
  • map
  • objectValues
  • removeDuplicates
  • slice
  • sort
  • splice
  • split
  • wrapWithArray

Booleans

  • toBoolean
  • toBooleanStrict

Date

  • nowDate
  • toDate

Objects

  • wrapWithObject

Strings

  • generateArcHash
  • htmlDecode
  • htmlToANS
  • interpolate
  • nitfToANS
  • replaceText
  • search
  • selectText
  • slugify
  • toCapitalize
  • toJSON
  • toLowerCase
  • toString
  • toTitleCase
  • toUpperCase
  • trim

concat(target, params) β†’ {Array.<any>}

A fn that takes two or more arrays and joins them into a single array.

Parameters:

NameTypeDescription
targetArray.<any>An array to concat your values to. Values are always applied to the end of the array.
paramsobject@see properties

Properties:

NameTypeDescription
valuesArray.<any>params.values: The array to add to the target array.

Returns:

Type: Array.<any>

filter(target, params) β†’ {Array.<T>}

A fn that runs the filter query on the target array.

Parameters:

NameTypeDescription
targetArray.<T>An array to apply the filter function to. If the target is not an array, it will be put into an array with target as the sole item.
paramsobject@see properties

Properties:

NameTypeAttributesDescription
querystringobjectThe JMESPath or XPath query. If the query is a string, that is the query value, and the query type is based on the document type. Provide a query object to set a query type.
valuestringThe JMESPath or XPath query.
typeSupportedFileTypes<optional>The query type aka the query engine to use. By default, the query type is based on the document type. However, if you know the target being acted on is of a different type, set this param. For example, if the source document type is XML but the target is a list of non-XML-element strings, then you must set query.type to β€œJSON” and query.value to a JMESPath query.

Returns:

Type: Array.<T>

Examples

// Source document is JSON in which item.images is a list of objects.
// Mappings:
{
"targetPath": "ANS.media.images",
"actions": [
{
"type": "def",
"query": "item.images"
},
{
"type": "fn",
"name": "filter",
"params": [
{
"query": "[?by!='John Smith']"
}
]
}
]
}
// The first action returns a list of item.images objects that gets passed into the filter fn as
// its target. The filter fn returns a list of only the objects whose "by" field is not equal to
// "Jonh Smith".
// Source document is XML in which /item/media nodes have a title child node.
// Mappings:
{
"targetPath": "ANS.media.images",
"actions":[
{
"type": "def",
"query": "/item/media/title/text()"
},
{
"type": "fn",
"name": "filter",
"params": [
{
"query": {
"value": "[?starts_with(@, 'tower') == `false`]",
"type": "json"
}
}
]
}
]
}
// The first action returns a list of text from title nodes ["bridge Y", "tower X", "bridge XYZ"].
// This isn't a list of XML nodes but is a JSON array of scalar values, and so we need to specify a
// params query object to tell filter to use the "json" query engine. The result of filter is the
// list: ["bridge Y", "bridge XYZ"].
// Note that this example is to show what a query object looks like; more likely you would have
// queries that return a list of XML nodes instead so that subsequent queries can stay as XPath.
// E.g. instead of "/item/media/title/text()", do "/item/media/title" and then the filter query
// will be an XPath query.

first(target) β†’ {T}

Extracts only the first item in an array

Parameters:

NameTypeDescription
targetT

Returns:

Type: T

flat(target) β†’ {Array.<any>}

A fn that takes array sub-elements in a target array and spreads them into the parent array.

Parameters:

NameTypeDescription
targetArray.<any>An array to apply the flat function to.

Returns:

Type: Array.<any>

generateArcHash(target, params) β†’ {string}

Modifies a target value by turning it into a string and encoding it into an arcId. Values used for your hash key are recommended to be unique for groups of documents.

Parameters:

NameTypeDescription
targetanyΒ 
paramsobject@see properties

Properties:

NameTypeAttributesDescription
hashstring<optional>A constant value to use for as your hash key. Is required if hashQuery is not provided.
hashQuerystring<optional>A query string used to locate a hash key. It is required if the hash is not provided.

Returns:

Type: string

htmlDecode(target) β†’ {string}

Modifies a target string value by decoding named or character references such as: foo &copy; bar &ne; baz &x1D306; qux -> foo B) bar b baz p qux

Parameters:

NameTypeDescription
targetstring

Returns:

Type: string

htmlToANS(target) β†’ {Record.<string, unknown>}

Modifies a target string by converting HTML to ANS.

Parameters:

NameTypeDescription
targetany

Returns:

Type: Record.<string, unknown>

interpolate(target, params) β†’ {string}

Modifies a target string value by interpolating by searching for ${?} and replacing them with queries

Parameters:

NameTypeDescription
targetstringΒ 
paramsArray@see properties

Properties:

NameTypeDescription
querystringThe query to use to locate values to apply to your target string.
target’source''dest’ Note: When set to source, it will apply your queries to your source document. When set to dest it will apply your queries to your target document.

Returns:

Type: string

join(target, params) β†’ {string}

A fn to join 2 or more strings together

Parameters:

NameTypeDescription
targetArray.<string>
paramsobjectsee properties

Properties:

NameTypeDescription
joinerstringparams.joiner: A string to join 2 or more values together

Returns:

Type: string

map(target, params:) β†’ {T}

Allows iteration over item(s) to execute item-scoped actions. Can be applied to an object or array of objects.

Parameters:

NameTypeDescription
targetobjectArray.<object>
params:MapTemplateparameters needed to execute

Returns:

Type: T

nitfToANS(target) β†’ {Record.string, unknown>}

Modifies a target nitf string it into ANS

Parameters:

NameTypeDescription
targetany

Returns:

Type: Record.<string, unknown>

nowDate() β†’ {string}

Returns the current date in UTC ISO String format.

Returns:

Type: string

objectValues(target) β†’ {Array.<T>}

Extracts only the values from a JSON object

Parameters:

NameTypeDescription
targetobject

Returns:

Type: Array.<T>

removeDuplicates(target) β†’ {Array.<T>}

Removes duplicate values from scalar arrays.

Parameters:

NameTypeDescription
targetArray.<T>

Returns:

Type: Array.<T>

replaceText(target, params) β†’ {string|Array.<string>}

Modifies a target value by searching the pattern in a string and replacing matches. fn can be applied to a string or string array.

Parameters:

NameTypeDescription
targetstringArray.<string>
paramsobject@see properties

Properties:

NameTypeAttributesDescription
patternstringA search pattern used to locate strings to replace
flagsstring<optional>Regular expression flags to apply to your target
replacementstringA string value for replacing pattern matches.

Returns:

Type: string|Array.<string>

search(target, param) β†’ {string}

A fn to allow for searching JSON/XML values against targets.

Parameters:

NameTypeDescription
targetany
paramobject

Properties:

NameTypeAttributesDescription
searchstringA query to search the document.
defaultValuestring<optional>When a query returns a null response the defaultValue will be used
type’json''xml’The type of the target value to search against

Returns:

Type: string

selectText(target, params) β†’ {string|Array.<string>}

Modifies a target value by getting a substring from text using regex . fn can be applied to a string or string array. It will return an array if it applies to an array and a string if it applies to a string.

Parameters:

NameTypeDescription
targetstringArray.<string>
paramsobject@see properties

Properties:

NameTypeDescription
patternstringA regex used to find strings to get

Returns:

Type: string|Array.<string>

slice(target, params) β†’ {Array.<any>}

A fn that removes items at the start to the end index and applies to the target output.

Parameters:

NameTypeDescription
targetArray.<any>An array to apply the splice function to
paramsobject@see properties

Properties:

NameTypeAttributesDescription
startnumberΒ params.start: The position to start from. Starts at 0.
endnumber<optional>params.end: The position of the array to end at.

Returns:

Type: Array.<any>

slugify(target, params) β†’ {string|Array.}

Modifies a target string by turning the string into a slug format. fn can be applied to strings or an array of strings.

Parameters:

NameTypeDescription
targetstringArray.<string>
paramsobject@see properties

Properties:

NameTypeAttributesDescription
useDefaultCharactersnumber<optional>params.useDefaultCharacters: When set to true, it will apply the following characters: ”*”, ”+”, ”~”, ”.”, ”(”, ”)”, ”’”, ’”’, ”!”, ”:”, ”@β€œ
charactersnumber<optional>params.characters: Any additional characters that need to be converted to ’-’

Returns:

  • returns a slugged string delimited with ’-’

Type: string|Array.<string>

sort(target) β†’ {Array.<string>|Array.<number>}

Sorts arrays with scalar values by their natural order

Parameters:

NameTypeDescription
targetArray.<string>Array.<number>

Returns:

Type: Array.<string>|Array.<number>

splice(target, params) β†’ {Array.<any>}

A fn that will take an array and remove elements from the target array. May be configured to return the deleted items and apply them to the target output.

Parameters:

NameTypeDescription
targetstringAn array to apply the splice function to
paramsobject@see properties

Properties:

NameTypeAttributesDescription
startnumberparams.start: The position to start from. Starts at 0.
deleteCountnumber<optional>params.deleteCount: The max number of items to delete.
itemsArray.<optional>params.items: The items to add to the array after removals.
returnDeletedItemsArray.<optional>params.returnDeletedItems: When set to false it returns the original target after modification. If true returns the deleted items from the array.

Returns:

Type: Array.<any>

split(target, params) β†’ {Array.<string>}

A fn to split a string into an array

Parameters:

NameTypeDescription
targetstringA string to apply the split function to
paramsobject@see properties

Properties:

NameTypeAttributesDescription
separatorstringparams.separator: A string delimiter to split on
limitnumber<optional>params.limit: The max number of delimiters to split on.

Returns:

Type: Array.<string>

toBoolean(target) β†’ {boolean}

Converts a value to a truthy/falsey value. Can be applied to a single value or an array of values.

Parameters:

NameTypeDescription
targetanyArray.<any> A value to convert to a boolean.

Returns:

Type: boolean

toBooleanStrict(target) β†’ {boolean|Array.<boolean>}

Converts a value strictly to a boolean value, such as: 'true' 'True' / 'False' 'false' -> true / false. Can be applied to a single value or an array of values.

Parameters:

NameTypeDescription
targetanyArray.<any> A value to convert to a boolean.

Returns:

Type: boolean|Array.<boolean>

toCapitalize(target) β†’ {string|Array.<string>}

Modifies a target string to capitalize a string. fn can be applied to strings or an array of strings.

Parameters:

NameTypeDescription
targetstringArray.<string>

Returns:

Type: string|Array.<string>

toDate(target) β†’ {string}

Converts a value to an UTC ISO String date. Can be applied to a single value or an array of values.

Parameters:

NameTypeDescription
targetanyArray.<any> A value to convert to a boolean

Returns:

Type: string

toJSON(target) β†’ {string}

Modifies a target JS object by converting it into a JSON string.

Parameters:

NameTypeDescription
targetany

Returns:

Type: string

toLowerCase(target) β†’ {string|Array.<string>}

Modifies a target string to a lowercase string. fn can be applied to strings or an array of strings.

Parameters:

NameTypeDescription
targetstringArray.<string>

Returns:

Type: string|Array.<string>

toString(target, params) β†’ {string|Array.<string>}

Modifies a target array by turning each element into a string. fn can be applied to strings or an array of strings.

Parameters:

NameTypeDescription
targetanyArray.<string>
paramsobject@see properties

Returns:

Type: string|Array.<string>

toTitleCase(target) β†’ {string|Array.<string>}

Modifies a target string to use title casing. fn can be applied to strings or an array of strings.

Parameters:

NameTypeDescription
targetstring / Array.<string>A string array to apply to join value to

Returns:

Type: string|Array.<string>

toUpperCase(target) β†’ {string|Array.<string>}

Modifies a target string to an uppercased string. fn can be applied to strings or an array of strings.

Parameters:

NameTypeDescription
targetstring / Array.<string>

Returns:

Type: string|Array.<string>

trim(target) β†’ {string|Array.<string>}

Modifies a target string by removing spaces on outer bounds of a character area. fn can be applied to strings or an array of strings.

Parameters:

NameTypeDescription
targetstring / Array.<string>

Returns:

Type: string|Array.<string>

wrapWithArray(target) β†’ {Array.<unknown>}

Wraps a target value inside an Array

Parameters:

NameTypeDescription
targetanyA value to wrap inside of an array

Returns:

Type: Array.<unknown>

wrapWithObject(target) β†’ {object}

Wraps a target value inside an object and the provided key.

Parameters:

NameTypeDescription
targetanyA value to wrap inside of an object

Returns:

Type: object

Mapping Usage

The header fields define general information about the map.

{
"id": "1234567890",
"name": "Test map",
"documentType": "json",
"description": "Converts RSS document fragments (captured from an RSS document) into ANS",
}
  • id - This is an auto-generated ID of the map to reference.
  • name - Defines the name of the map.
  • documentType - Defines what type of source document is being used.
    • xml - for XML source documents. For XML source documents, mapping uses XPath syntax to query source documents. You can find out more about XPath syntax here.
    • json - for JSON source documents. For JSON source documents, mapping uses JMESPath syntax to query source documents. You can find out more about JMESPath syntax here.
  • description - Add a helpful note about what this map is designed to convert.

mappings

The mappings array defines how to build a specific target JSON result.
Each object in the mappings array should:

  • The root object must be of type object and must have targetPath and actions properties.
  • targetPath must be a string.
  • actions must be an array of objects, each with specific properties:
    • type must be a string and can only be either 'def' or 'fn'.
      • When type is set to def action object can have the following properties:
        • set which set static value to target path and can be of type number, integer, string, boolean, array, or object.
        • query which queries source document (XPath for XML and JMESPath for JSON) and must be a string containing the query which will use the query engine matching the source document type, or an object to use a different query engine. For example, if the source document is XML but you want to query against JSON, then specify query: { value: 'a JMESPath query'; type: 'json' }.
      • When type is set to fn action object can have the following properties:
        • name must be a string
        • params must be an array with items that can be of type number, integer, string, boolean, array, or object.
{
"targetPath": "subheadlines",
"actions": [
{
"type": "def",
"query": "title"
}
]
}

Will produce in the target JSON

{
"subheadlines": "whatever result comes from querying title of source doc"
}
{
"targetPath": "ANS.created_date",
"actions": [
{
"type": "def",
"query": "created"
},
{
"type": "fn",
"name": "toDate"
}
]
}

Will produce in the target JSON

{
"ANS" : {
"created_date": "converts created date from source doc for i.e. 2024-02-06T15:40:00.000Z"
}
}

static value

The simplest type of mapping is to create a field using a static value like:

"mappings": [
{
"targetPath": "type",
"actions": [
{
"type": "def",
"set": "story"
}
]
}
]

This will generate the JSON target

{ "type": "story" }

query source value

The most common use case for a map is to import data from a source document to a new target document.

All examples on this page will use this as the source XML document fragment:

<item>
<title>Todays weather forecast </title>
<pubDate>22 Oct 2022 13:05:22 GMT </pubDate>
</item>

Since the source is XML documentType will be set as xml.

Let’s add a second object to the mappings array to map the <title> tag in the source to headlines.basic in the JSON target. To get the contents of the <title> tag inside the <item> tag we use slashes to join the tags in the order we want to search for them, like /item/title, and append the command text() to tell it we just want the contents of the tag. XPath always returns values as an array, even from the text function, so the string function wraps this to define we only want the inner string value.

"mappings": [
{
"targetPath": "type",
"actions": [
{
"type": "def",
"set": "story"
}
]
},
{
"targetPath": "headlines.basic",
"actions": [
{
"type": "def",
"query": "string(/item/title/text())"
}
]
}
]

This will generate the following JSON target document:

{
"type": "story",
"headlines": {
"basic": "Todays weather forecast "
}
}

Modifying values with function

A common need is to make formatting changes to a source before it is added to a target. For instance, maybe you want to make the text uppercase. This functionality is provided by defining a function array in any mappings object. There are many out of the box functions available to use with no code needed in the map.

Let’s add a functions array to our example mappings object. To remove leading and trailing spaces from the title in our source example we use trim. To then also make it a Title Case, we use toTitleCase. These are simple processors that do not need any arguments to do their job, and so all that is needed is to list their names as strings in the order we wish them to be applied, and they will manipulate the value assigned to the targetPath. So:

{
"targetPath": "type",
"actions": [
{
"type": "def",
"set": "story"
}
]
},
{
"targetPath": "headlines.basic",
"actions": [
{
"type": "def",
"query": "string(/item/title/text())"
},
{
"type": "fn",
"name": "trim"
},
{
"type": "fn",
"name": "toTitleCase"
}
]
}

Will generate the following JSON target:

{
"type": "story",
"headlines": {
"basic": "Todays Weather Forecast"
}
}

conditional value

Sometimes one or more true/false conditions might be needed to determine if a targetPath should be added to the target document. For this purpose, a conditions array can be added. If our example XML might sometimes have a <slug> tag nested in <items> we could just map it like this:

mappings: [
...
{
"targetPath": "slug",
"actions": [
{
"type": "def",
"query": "string(/item/slug/text())"
}
]
}
]

If there is a <slug> tag inside <item> then the slug field value will be added as string to the target path slug. But if there isn’t a slug field, nothing will happen. The map engine will not add an empty field, so you don’t need to add conditions on every mappings object.

In the example below when there is no slug tag in the source XML, the output from the first mappings object will be nothing. The second mappings object will evaluate the condition as true, and so it will use the title tag’s content and modify it with the slugify processor to produce the value of slug in the target.

mappings: [
...
{
"targetPath": "slug",
"conditions": [
true,
"string(/item/slug/text()) != null"
],
"actions": [
{
"type": "def",
"query": "string(/item/slug/text())"
},
{
"type": "fn",
"name": "slugify",
"params": [
{
"useDefaultCharacters": true
}
]
}
]
}
]

Generating the following in JSON target document:

{
"slug": "todays-weather-forcast"
}