[SalesForce] Journey Builder API Event

I am using API event as a journey source in journey.
I am firing this api from apex trigger on creation/updation of records.
Below is the API:

Post: https://<subdomain>/interaction/v1/events
Headers: Content-type: application/json
         Authorization Bearer <Access-token>
Body: 
          {
                      "ContactKey":"vid1",
                      "EventDefinitionKey":"APIEvent-bc257d7e-36a2-c154-7016-7fc316e5b6d8",
                      "Data":{
                      "VID":"vid1",
                      "Work_Email__c":"abc@psl.com",
                      "First_Name__c":"Manali",
                      "Last_Name__c":"Horane"


                      }
                      }

I am using data extension without any primary key but it has subscriber key as unique id 'vid.
When API event fired on record creation trigger, DE populated with one record, again when API event fired on same record update trigger, DE gets populated with duplicate records.
I want to maintain unique updated records in Data extension. Is there any way of maintaining unique records?
Or do I need to use automation activities like script activity or SQL activity for maintaining latest updated unique records in separate DE?

Note: unfortunately if data extension has primary key as 'vid' and when API event fires with same updated record data whose primary key(vid) is already present in Journey data extension it gives error as below:

{
    "message": "The event data contains duplicate value for an existing primary key. Please correct the event data and try again.",
    "errorcode": 30000,
    "documentation": ""
} 

Hence Primary key can not be used when API gets triggered multiple times for the same primary key.

Best Answer

Clever catch! Though there might be better solutions based on your requirement. Below is one of the WORK Around for this glitch in API based journeys!

You can manually update all the records to have the LATEST STATUS using UpdateData() method.. [though multiple records exists, all of them will be overwritten with updated status for a particular contact/subscriber.]

Code from my solution [removed business specific columns] Please check out the /* WORK Around: section in below code.

<!-- Journey Processing page : START -->
%%[
    SET @subkey = QueryParameter('subkey')
    SET @FirstName = QueryParameter('FirstName')
    SET @email = QueryParameter('email')
    SET @Subscription_Status = QueryParameter('Subscription_Status') 
   /*Generating the AccessToken using client id and secret key*/
   VAR @callstatus, @response
   SET @payload = '{"client_id": "xxxxxxxxx", "client_secret": "xxxxxxxxxx", "grant_type": "client_credentials"}'
   SET @accessToken = HTTPPost2("https://xxxxxxxx.auth.marketingcloudapis.com/v2/token", "application/json", @payload, True, @callstatus, @response)
   ]%% 
   <script runat="server">
   /*Framing the API content and extracting only access token from the above response*/
   Platform.Load("core", "1");
   var subkey = Variable.GetValue("@subkey");
   var FirstName = Variable.GetValue("@FirstName");
   var email = Variable.GetValue("@email");
   var Subscription_Status = Variable.GetValue("@Subscription_Status");
   var accessTok = Variable.GetValue("@callstatus");
   var response_ = Platform.Function.ParseJSON(accessTok);
   var accessToken_ = response_.access_token;
   var content = { "ContactKey": subkey, 
       "EventDefinitionKey":"xxxxxx", 
       "EstablishContactKey": true, 
       "Data": { 
          "email address": email,
          "FirstName":FirstName,
          "Subscription_Status":Subscription_Status,
          "Contact Key":subkey }}
   var strContent = Platform.Function.Stringify(content);
   Variable.SetValue("@token_",'Bearer '+accessToken_); 
   Variable.SetValue("@content",strContent);
   </script>   %%[
   /*Invoking the journey API*/
   var @statusCode
   var @response
   SET @post = HTTPPost2("https://xxxxxxxx.rest.marketingcloudapis.com/interaction/v1/events","application/json",@content,false,@statusCode, @response, "Authorization", @token_)


 /* WORK Around: Contact already exists in Journey, hence update SUBSCRIPTION STATUS of ALL records of respective contact : START*/
 SET @lookUp = LookupRows('<Your Journey DE Name>','Contact Key', @subkey)
 SET @rowCount = Rowcount(@lookUp)
 IF @rowCount > 0 THEN 
   SET @updatestatusField = UpdateData('<Your Journey DE Name>',1,'Contact Key',@subkey,'Subscription_Status',@Subscription_Status)
 ENDIF
  /* WORK Around: Contact already exists in Journey, hence update SUBSCRIPTION STATUS of ALL records of respective contact : END*/
 ]%%

 %%=v(@token_)=%% <br/>
 %%=v(@statusCode)=%% <br/>
 %%=v(@content)=%%<br/>
<!-- LIVE:: Processing page : END -->
Related Topic