Copy URL endpoint

The purpose of the Copy URL endpoint is to copy an existing service instance and create a new service instance. AMS passes both the original service instance and the new service instance to the service's Copy URL. This is to enable the app developer the flexibility of storing or copying information (such as record definition) from the original service instance with the new service instance.

Note: If a Copy URL is not provided, AMS will treat copy as create, and call the app's Create URL instead.

Workflow

The following diagram illustrates the process of copying a service.

Service Copy URL endpoint

AMS calls the service's Copy URL endpoint with the following request.

Service URL

<service-baseUrl><service-copyUrl>

Request Method

POST

Request Header

Authorization: Bearer <JWT>

Content-Type=application/json

Bearer Token

JWT claims

When AMS is making the request to the App, the key and value pairs bear the following meanings:

Key Value Definition Context
iss The issuer of the token. Issuer is AMS
sub The subject of the token. Set to the app's associated product uuid.
aud The audience of the token. The App's Token Key.
exp The date and time the token will expire, expressed as a Unix timestamp. Must be after the current date/time. Set to 60 seconds after the JWT was created.
iat The date and time the JWT was issued, expressed as a Unix timestamp. Set to the current time.
jti The unique identifier for the JWT token. Set to a random UUID
o.a.p.ctenantId The tenant Id. Set to the id of the tenant as identified by the product
o.a.p.cproductUUID The product UUID. Set to the product's UUID.
o.a.p.cproductName The product name. Set to the product's name.
o.a.p.csourceRequest The source of the request. Set to the product's UUID.
o.a.p.cdestinationId The destination Id. Set to the app's token key (found in app details)
o.a.p.cdestinationUrl The destination URL. Set to the service instance creation URL (the service's base URL + the service's create URL. These URLs are found in service details.

Signature

Signed with an app's token secret.

When a service instance is copied, AMS sends the following payload to the app:

POST <service-base-url><service-copy-url>
Authorization: Bearer <JWT>
{
    "originalApplicationServiceInstance": {
        "status": "CREATED",
        "assetId": "3iojr3d908",
        "assetType": "campaign",
        "uuid": "4420fa19-e8f6-4cdf-9754-d876dea3002f",
        "secret": "c4321e9f-19a7-48b2-9796-c21142c709c9-fb24667dde63-4b6a-99af-10b23122a6d0",
        "recordDefinition": {
            //some valid record definition
            ...
        },
        "applicationServiceInstall": {
            "uuid": "40fe3760-a487-4e89-8cf5-2d3e06977623",
            "name": "Demo transform service for developer's test",
            "description": "Demo transform service for developer's test",
            "invokeUrl": "https://b3a3ba42.ngrok.io/CX-app-demo-1.0/rest/1.0/services/1/invoke",
            "smallLogo": "https://www.iconexperience.com/_img/o_collection_png/green_dark_grey/48x48/plain/delivery_truck.png",
            "mediumLogo": "https://www.iconexperience.com/_img/o_collection_png/green_dark_grey/128x128/plain/delivery_truck.png",
            "largeLogo": "https://www.iconexperience.com/_img/o_collection_png/green_dark_grey/256x256/plain/delivery_truck.png",
            "maxBatchSize": 200,
            "application": {
                "uuid": "b95d7bea-0154-47b8-81ca-ea4e35e784a9",
                "name": "Demo App",
                "description": "It is a demo app",
                "baseUrl": "https://oap.p01.elqqa01.com/awesome-app",
                "statusUrl": "/status",
                "installUrl": "/install",
                "configureUrl": "/configure",
                "uninstallUrl": "/uninstall",
                "saveConfigurationUrl": "/save",
                "smallLogo":"https://images.martechadvisor.com/images/uploads/product_logos/Oracle%20Responsys.jpeg",
                "mediumLogo":"https://images.martechadvisor.com/images/uploads/product_logos/Oracle%20Responsys.jpeg",
                "largeLogo":"https://images.martechadvisor.com/images/uploads/product_logos/Oracle%20Responsys.jpeg",
                "status": "UP",
                "providerUuid": "9dbda2d4-e9ac-4aab-8886-be0402a662cb"
            },
            "serviceType": {
                "name": "ACTIVITY",
                "externalName": "Activity",
                "description": "This service will ingest data and send it to an external service or process it to return back a status or modified data"
            },
            "installUuid": "05860261-2f24-4639-ae38-3616306e3f2d",
            "productName": "Responsys",
            "providerName": "ResponsysApps",
            "status": "UP"
        }
    },
    "newApplicationServiceInstance": {
        "status": "CREATED",
        "assetId": "k2lr4ijosd",
        "assetType": "campaign",
        "uuid": "8088b46e-93f3-4c71-b7c3-96a7d9dc9293",
        "secret": "c8292396-2ab3-4bb8-b6de-f651d3704f6b-62d71c64-1de9-476a-ac34-4f7ac1cc300e",
        "recordDefinition": null,
        "applicationServiceInstall": {
            "uuid": "40fe3760-a487-4e89-8cf5-2d3e06977623",
            "name": "Demo transform service for developer's test",
            "description": "Demo transform service for developer's test",
            "invokeUrl": "https://b3a3ba42.ngrok.io/CX-app-demo-1.0/rest/1.0/services/1/invoke",
            "smallLogo": "https://www.iconexperience.com/_img/o_collection_png/green_dark_grey/48x48/plain/delivery_truck.png",
            "mediumLogo": "https://www.iconexperience.com/_img/o_collection_png/green_dark_grey/128x128/plain/delivery_truck.png",
            "largeLogo": "https://www.iconexperience.com/_img/o_collection_png/green_dark_grey/256x256/plain/delivery_truck.png",
            "maxBatchSize": 200,
            "application": {
                "uuid": "b95d7bea-0154-47b8-81ca-ea4e35e784a9",
                "name": "Demo App",
                "description": "It is a demo app",
                "baseUrl": "https://oap.p01.elqqa01.com/awesome-app",
                "statusUrl": "/status",
                "installUrl": "/install",
                "configureUrl": "/configure",
                "uninstallUrl": "/uninstall",
                "saveConfigurationUrl": "/save",
                "smallLogo":"https://images.martechadvisor.com/images/uploads/product_logos/Oracle%20Responsys.jpeg",
                "mediumLogo":"https://images.martechadvisor.com/images/uploads/product_logos/Oracle%20Responsys.jpeg",
                "largeLogo":"https://images.martechadvisor.com/images/uploads/product_logos/Oracle%20Responsys.jpeg",
                "status": "UP",
                "providerUuid": "9dbda2d4-e9ac-4aab-8886-be0402a662cb"
            },
            "serviceType": {
                "name": "ACTIVITY",
                "externalName": "Activity",
                "description": "This service will ingest data and send it to an external service or process it to return back a status or modified data"
            },
            "installUuid": "05860261-2f24-4639-ae38-3616306e3f2d",
            "productName": "Responsys",
            "providerName": "ResponsysApps",
            "status": "UP"
        }
    }
}

Tip: The JWT Token in the Authorization Header is generated by following the AMS to App token generation. For more information about this call, including authentication details, see the endpoint API reference.

App's response to the Copy URL request

The service's Copy URL endpoint may either send back an empty response or a record definition. If the app responds with a 2xx response code, a service instance is created. It is up to the app developer to determine what they would like to store or copy from the original service instance.

Sample code for a record definition response
@RequestMapping(value = "/copy", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
public ResponseEntity copyServiceInstance(@RequestBody ServiceInstanceCopyRequestDTO requestBody) {
 
    ModelMapper mapper = new ModelMapper();
 
    if (requestBody == null) {
        throw new IllegalArgumentException("Empty payload sent to create url");
    }
     
    // See ModelMappingConfiguration.java for how ServiceInstance is populated from ServiceInstanceCreateRequestDTO
    ServiceInstance newServiceInstance = mapper.map(requestBody.getNewInstance(), ServiceInstance.class);
     
    // New service instance will copy the record definition from the original service instance.
    newServiceInstance.setRecordDefinition(requestBody.getOriginalInstance().getRecordDefinition());       
 
 
    // New service instance will copy the configuration mappings stored by the app
    ServiceInstance originalServiceInstance = serviceInstanceService.getEntity(
            requestBody.getOriginalApplicationServiceInstance().getUuid());
    newServiceInstance.setConfig(originalServiceInstance.getConfig());
    newServiceInstance.setStatus(originalServiceInstance.getStatus());
     
    serviceInstanceService.addEntity(newServiceInstance);
    return new ResponseEntity<RecordDefinitionDTO>(newServiceInstance.getRecordDefinition(), HttpStatus.OK);
}

Note: Both AMS and the app should save service instances and be in sync.

Sample JSON payload for a record definition

If responding with a record definition, the record definition must resemble the following. See Record definitions for more information.

Learn more

Developing Apps for CX Apps

Service Invocation