SK SKYVVA Documentation

18. SkyvvaSalesforce Receiver Adapter — Platform Event Publishing

1. Overview

This tutorial uses the SkyvvaSalesforce receiver adapter → Skyvva → Platform Event - Publishing to send a posted-invoice notification to Salesforce. CPI validates and maps the invoice; a Salesforce Flow receives the event and creates an Invoice Notice.

Postman represents the ERP system in this tutorial. ERP means Enterprise Resource Planning, such as SAP S/4HANA or SAP ECC, where invoices are created and posted. Use Postman to send the sample invoice and view CPI's response; no real ERP connection is required.

The example uses JSON for input/output and XML for validation and Message Mapping, with standard CPI steps.

2. Context Before You Start

2.1 Business situation and why use it

A distributor manages invoicing in ERP and customer relationships in Salesforce. Sales representatives need to see posted invoices without waiting for a nightly export. The ERP sends the customer number, invoice number, amount, currency, and posting time after its invoice transaction has committed.

Business valueExample
ERP customer number0000100451
Invoice number90001067
Invoice amountUSD 1250.75
Business message IDERP-INVOICE-90001067-POSTED-01

This is a fictional invoice-notification example. ERP remains responsible for accounting; the event tells Salesforce that posting has already occurred.

Use events for asynchronous follow-up work. Use a record operation when the caller needs an immediate Salesforce record result.

2.2 How the flow works

ERP → Receive Posted Invoice → InvoiceJsonToXml → ValidateInvoiceXml
    → CheckInvoiceRules ── valid → MapInvoiceToEvent → SetEventContentType
    → PublishInvoice → SetResponseHeaders → Return Publication Confirmation → ERP

CheckInvoiceRules ── default → RejectInvoice (Error End)

PublishInvoice ⇄ SKYVVA receiver: Platform Event - Publishing ⇄ Salesforce event bus

Salesforce event bus → Platform Event–Triggered Flow → Invoice Notice

The SKYVVA Integration and Interface identify the target event. CPI performs the mapping and publishes through Salesforce Pub/Sub.

ERP receives a response after publication. It does not wait for the Salesforce subscriber to finish. status = SUCCESS acknowledges event publication; it does not confirm that an Invoice Notice exists.

3. Prerequisites

4. Create the Salesforce event

The custom Platform Event defines the notification “ERP has posted this invoice” and the fields subscribers receive, such as customer, invoice number and amount.

You can reuse a suitable existing event. Keep its API name and fields consistent across the SKYVVA Interface, CPI mapping and subscriber Flow.

  1. In Salesforce Setup, search Platform Events and select New Platform Event.
  2. Enter Label ERP Invoice Posted, Plural Label ERP Invoices Posted, and Object Name ERP_Invoice_Posted.
  3. Confirm API name ERP_Invoice_Posted__e, high-volume event support, and Deployment Status Deployed.
  4. Keep Publish Behavior = Publish Immediately and save. This setting does not coordinate the Pub/Sub call with ERP; send only after ERP commits the invoice.
  5. Add the custom fields below through the event's Custom Fields & Relationships → New action.
LabelAPI nameType and size
Message IDMessage_ID__cText(80)
ERP Customer IDERP_Customer_ID__cText(30)
Invoice NumberInvoice_Number__cText(30)
Gross AmountGross_Amount__cNumber: Length 16, Decimal Places 2
Currency CodeCurrency_Code__cText(3)
Invoice StatusInvoice_Status__cText(20)
Posted AtPosted_At__cText(30), UTC ISO timestamp contract

All seven fields are required by this example. Section 8 configures validation for positive USD invoices with status POSTED.

Grant the integration user Create access to the event and configure the subscriber's access to its destination object.

Figure 1. Custom fields of the ERP Invoice Posted event.

5. Configure the SKYVVA Integration and Interface

  1. Open the SKYVVA Integration area in Salesforce and create an Integration named ERP Invoice Events, or use an existing dedicated Integration.
  2. Within that Integration, create an Interface with Interface Name = ERP Invoice Posted. Use the business interface name, not the generated Salesforce record number.
  3. Select Interface Direction = InBound because the notification enters Salesforce.
  4. Set Source/Target Name to ERP_Invoice_Posted__e. Depending on the screen, this field can appear as Source Name or Salesforce Object. Confirm its saved value is the event API name.
  5. Select Operation Type = Publish Salesforce Event where required by the Interface form. Complete required fields according to your org's Interface creation policy, save, and make the Interface available to the integration user.
  6. Confirm this Interface name is unique within the named Integration and that its Integration relationship points to ERP Invoice Events.

The publisher uses these Integration/Interface names to resolve /event/ERP_Invoice_Posted__e. No Channel Name entry is needed on the receiver screen.

No SKYVVA mapping rows or response Interface are required; field mapping is configured in CPI.

Why is External Mapping not used? This operation publishes directly through Salesforce Pub/Sub. It uses the Interface to identify the event and does not run the SKYVVA mapping engine. CPI Message Mapping prepares the event fields, so enabling the Interface's External Mapping flag does not change this publishing path.

If you change the event API name on an existing Interface, restart or redeploy the iFlow to refresh its cached selection.

Figure 2. SKYVVA Interface identifying the invoice event.

6. Create a simple Salesforce subscriber

To make the received event visible, create a Platform Event–Triggered Flow that saves an Invoice Notice:

Start: ERP Invoice Posted → Create Invoice Notice

6.1 Create the destination object

The custom Invoice Notice object stores the received invoice information so users can view, search and report on it. The subscriber Flow copies event values into this record; publication alone does not create it.

For a real business process, you can use a suitable existing object and adjust the Flow mappings instead.

In Setup → Object Manager → Create → Custom Object, create Invoice Notice (Plural Label Invoice Notices, Object Name Invoice_Notice). Set its Record Name to Invoice Notice Number, Type to Auto Number, Display Format to IN-{00000}, and Starting Number to 1.

Under Fields & Relationships, add these fields. Reuse the object and fields if you already created them.

Field API nameType
Message_ID__cText(80), Unique
ERP_Customer_ID__cText(30)
Invoice_Number__cText(30)
Gross_Amount__cNumber: Length 16, Decimal Places 2
Currency_Code__cText(3)
Posted_At__cText(30)
Processing_Status__cText(30)

Give the users verifying the result access to Invoice Notice and its fields, and make its records available through a custom tab or your Salesforce application.

6.2 Configure the Flow

  1. Open Setup → Flows → New Flow → Platform Event–Triggered Flow.
  2. In Start, select the invoice event created in section 4. Use the actual API name in your org (ERP_Invoice_Posted__e, or your existing ERP_Invoices_Posted__e).
  3. Add Create Records with Label Create Invoice Notice and API Name Create_Invoice_Notice.
  4. Choose One record. Under How to set record field values, select Manually ("Select an object and configure the record values manually"), then choose Invoice Notice as the object. Select the incoming $Record fields through the value resource picker for each mapping. Add these mappings:
Invoice Notice fieldValue resource or literal
Message_ID__c{!$Record.Message_ID__c}
ERP_Customer_ID__c{!$Record.ERP_Customer_ID__c}
Invoice_Number__c{!$Record.Invoice_Number__c}
Gross_Amount__c{!$Record.Gross_Amount__c}
Currency_Code__c{!$Record.Currency_Code__c}
Posted_At__c{!$Record.Posted_At__c}
Processing_Status__cLiteral text Recorded
  1. Leave the auto-number Name and any existing optional Account lookup unmapped.
  2. Connect Start → Create Invoice Notice. In Auto-Layout, add the element using + beneath Start; in Free-Form, draw the connection. The successful branch ends after Create Records.
  3. Save as Record ERP Invoice Notice, API Name Record_ERP_Invoice_Notice, resolve validation errors, and activate the Flow.

Ensure only the intended subscriber version is active for the test.

6.3 Verify receipt

After publishing the valid sample in section 10, allow time for asynchronous processing, then find the Invoice Notice by Message ID. Verify invoice 90001067, customer 0000100451, amount 1250.75, currency USD, posting time 2026-10-10T07:30:00Z, and status Recorded.

Use a new Message ID for each new test notification. Reusing one can fail notice creation because its Message ID field is unique.

Figure 3. Activated Salesforce subscriber Flow for the invoice event.

7. Create the SAP Integration Suite iFlow and connection

Create ERP Posted Invoice to Salesforce Event using the diagram in section 2.2. Configure its sender and receiver below, then add the processing steps from sections 8–9.

7.1 HTTPS sender

SettingExample configuration
GeneralName ReceivePostedInvoice
Connection → Address/erp/invoices/posted
AuthorizationUser Role; tenant-approved caller role, commonly ESBMessaging.send
Incoming method/bodyCaller sends POST with Content-Type application/json
CSRF and other optional settingsFollow the tenant's approved inbound policy; if CSRF is enabled, the caller obtains and sends token/cookies

Use the deployed CPI endpoint and caller authentication, separate from Salesforce receiver credentials. Set Integration Process Transaction Handling to Not Required.

7.2 Receiver credentials and Connection tab

In SAP Integration Suite Security Material, deploy a User Credentials artifact named skyvva-client-credentials. Set User to the Salesforce application Client ID and Password to its Client Secret. This adapter reads that artifact type for Client Credential authentication.

Tab/fieldValue
GeneralReceiver channel name PublishInvoiceEvent; SkyvvaSalesforce adapter
Connection → Authentication TypeOAuth2
Connection → OAuth2 FlowClient Credential
Connection → Login UrlYour Salesforce My Domain base address, for example https://your-domain.my.salesforce.com
Connection → Client Credentialskyvva-client-credentials
Connection → User CredentialHidden for the selected OAuth2 flow

Do not append /services/oauth2/token to Login Url. The administrator must enable the application flow and configure its run-as user before you test.

7.3 Receiver Processing tab

Field/groupValueWhy
Processing TypeSkyvvaUses SKYVVA Interface metadata to locate the event
OperationPlatform Event - PublishingSelects the event publisher
IntegrationERP Invoice EventsMust match the saved Integration name
InterfaceERP Invoice PostedMust match Interface Name within that Integration
Format → Request FormatApplication/XMLMatches the graphical mapping output
Format → Response FormatApplication/JSONSupplies the acknowledgement returned unchanged to ERP
Adapter Settings → Logging optionDefaultNormal SAP Integration Suite adapter logging
Enable retry for fatal connectivity errorsDisabledThis HTTP setting does not supply a complete Pub/Sub business-retry procedure
HTTP client timeout (sec)Keep default 60HTTP login/metadata setting; it is not a Pub/Sub publish deadline

The Interface supplies the event name. Leave unrelated API Version/Mode settings unchanged. Reconcile an uncertain publication before retrying.

Figure 4. Receiver settings for Platform Event Publishing.

8. Map the ERP invoice to one event

Convert the invoice to XML, validate it, then map its fields to the Salesforce event.

8.1 Agree the input contract

Send one invoice object with text identifiers, a numeric amount and a UTC timestamp ending in Z. ERP must convert timestamps to UTC before sending; this route does not perform timezone conversion.

Copy the following JSON into Postman. You can also save it locally as erp-invoice-utc.json:

{
  "messageId": "ERP-INVOICE-90001067-POSTED-01",
  "customerNumber": "0000100451",
  "invoiceNumber": "90001067",
  "grossAmount": 1250.75,
  "currency": "USD",
  "status": "POSTED",
  "postedAt": "2026-10-10T07:30:00Z"
}

Keep identifiers quoted to preserve leading zeros. Enforce JSON types in ERP/API input validation: after XML conversion, the validator cannot distinguish JSON numbers from quoted numeric strings.

8.2 Convert ERP JSON to XML

Add a JSON to XML Converter named InvoiceJsonToXml after Start:

Processing settingValue
Add XML Root ElementSelected
NameInvoice
Root namespaceEmpty
Use Namespace MappingDisabled

Its output should contain one Invoice root and the seven ERP field names. Save the following sample as erp-invoice.xml for mapping simulation; Postman sends the JSON above.

<?xml version="1.0" encoding="UTF-8"?>
<Invoice>
  <messageId>ERP-INVOICE-90001067-POSTED-01</messageId>
  <customerNumber>0000100451</customerNumber>
  <invoiceNumber>90001067</invoiceNumber>
  <grossAmount>1250.75</grossAmount>
  <currency>USD</currency>
  <status>POSTED</status>
  <postedAt>2026-10-10T07:30:00Z</postedAt>
</Invoice>

8.3 Validate before publishing

Have your integration developer prepare and upload ERPInvoiceValidation.xsd using the rules below. This schema defines the required fields and allowed values.

FieldCheck before publishing
Message IDRequired text, maximum 80 characters
Customer numberRequired text containing 1–30 digits; keep leading zeros
Invoice numberRequired text, maximum 30 characters
Gross amountGreater than zero, below 10000000000000000, with at most two meaningful decimal places
CurrencyUSD
StatusPOSTED
Posted atValid UTC date/time ending in Z
Message structureOne invoice with exactly the seven expected fields, each appearing once; allow any field order

Add XML Validator → ValidateInvoiceXml, select the schema and keep Prevent Exception on Failure disabled. Message Mapping alone does not run this validation.

After the validator add a Router named CheckInvoiceRules. On the valid route choose Expression Type = XML and use this XPath condition:

not(/Invoice/*[
  normalize-space(substring(string(.), 1, 1)) = ''
  or normalize-space(substring(string(.), string-length(string(.)), 1)) = ''
])
and string-length(/Invoice/postedAt) <= 30

This is an XPath validation condition, not a Groovy script. It rejects field values with leading or trailing XML whitespace and checks that postedAt is no longer than 30 characters. Connect the valid route to Message Mapping and the Default Route to an Error End named RejectInvoice.

This extra check supports the tutorial’s input rules; Platform Event publishing itself does not require this Router. If your sending system already enforces these rules, you can omit CheckInvoiceRules and its RejectInvoice branch, then connect ValidateInvoiceXml → MapInvoiceToEvent directly. Keep the XML Validator.

8.4 Create the graphical Message Mapping

Have your integration developer prepare the two mapping XSDs from the field table below. Add Message Mapping → MapInvoiceToEvent, create/select its mapping resource and choose:

SideSchemaRoot
SourceERPInvoice.xsdInvoice
TargetInvoiceEvent.xsdInvoiceEvent

Use no target namespace. These schemas describe the mapping; the Salesforce fields are created separately in section 4.

Connect each ERP field to the matching Salesforce field:

ERP fieldSalesforce event fieldValue type
messageIdMessage_ID__cText
customerNumberERP_Customer_ID__cText; preserve leading zeros
invoiceNumberInvoice_Number__cText
grossAmountGross_Amount__cDecimal number
currencyCurrency_Code__cText
statusInvoice_Status__cText
postedAtPosted_At__cUTC date/time input → text event field

Save and select the mapping. Run Simulation with erp-invoice.xml from section 8.2 and compare with this expected output:

<InvoiceEvent>
  <Message_ID__c>ERP-INVOICE-90001067-POSTED-01</Message_ID__c>
  <ERP_Customer_ID__c>0000100451</ERP_Customer_ID__c>
  <Invoice_Number__c>90001067</Invoice_Number__c>
  <Gross_Amount__c>1250.75</Gross_Amount__c>
  <Currency_Code__c>USD</Currency_Code__c>
  <Invoice_Status__c>POSTED</Invoice_Status__c>
  <Posted_At__c>2026-10-10T07:30:00Z</Posted_At__c>
</InvoiceEvent>

Check the seven fields, leading zeros, amount and timestamp. Section 10 tests the deployed flow.

8.5 Publish the mapped XML

Add a Content Modifier named SetEventContentType after mapping. In Message Header create a Constant Content-Type header with value application/xml; leave the body unchanged. Connect to PublishInvoice, the Request Reply step using the PublishInvoiceEvent SkyvvaSalesforce receiver channel from section 7. Set Request Format = Application/XML and Response Format = Application/JSON.

Send one InvoiceEvent root with its seven field children, without an extra envelope or records array. No XML-to-JSON Converter is needed before publishing.

Figure 5. Complete CPI iFlow for invoice validation, mapping and publication.

Figure 6. Message Mapping from ERP invoice fields to Salesforce event fields.

9. Return publication confirmation to ERP

The response returns to the caller—Postman in this tutorial.

After PublishInvoice, add a Content Modifier named SetResponseHeaders. In Message Header create these Constant entries, leaving the Message Body unchanged:

NameValue
Content-Typeapplication/json
CamelHttpResponseCode200

Connect it to the normal End, Return Publication Confirmation, on the successful path.

Return the adapter acknowledgement unchanged:

{"status":"SUCCESS","message":"Platform event published","replayId":"AQID"}
Response itemMeaning
status = SUCCESSThe adapter reports acknowledged event publication.
messageThe adapter's publication-result description.
replayIdOpaque event replay identifier represented as Base64. AQID is illustrative; actual values vary. It is not an invoice or ERP Message ID.
HTTP 200The request completed under this publication contract; it does not confirm subscriber business processing.

Keep the acknowledgement body unchanged. Retain the request's original messageId for business reconciliation.

Verify subscriber processing separately by finding the matching Invoice Notice, as described in section 6.3.

Figure 7. Publication acknowledgement displayed in Postman.

Figure 8. Invoice Notice created by the Salesforce subscriber.

10. Testing with Postman

  1. Save and deploy the iFlow; activate the Salesforce subscriber from section 6.
  2. Copy the endpoint from Monitor → Manage Integration Content.
  3. In Postman, select POST, enter that URL and configure the HTTPS sender's required authentication.
  4. Set Content-Type = application/json. Choose Body → raw → JSON, paste the section 8.1 sample and send.
  5. Check Postman's response, the CPI execution under Monitor → Monitor Message Processing, and the saved Invoice Notice.
TestExpected result
Valid UTC sample invoiceHTTP 200 with adapter status SUCCESS, message Platform event published and a nonempty replayId; verify the Invoice Notice separately
Missing customer, blank message ID or status DRAFTXML Validator or Router rejects before publication
Non-UTC timestamp, invalid calendar date or timestamp longer than 30 charactersXML Validator or Router rejects before publication
Numeric customerNumber or quoted grossAmount in JSONEnforce JSON types in ERP/API input validation; XML conversion loses those original JSON types
Amount 1250.755, zero, negative, or currency other than USDContract validation rejects before publication
Wrong Integration/Interface, blank source name, or Account as sourceTopic resolution fails; no success response
Event publishing permission absentPublication fails; investigate integration-user access
Publish or caller timeoutResult can be uncertain; reconcile before resend using the stable Message ID

Find the notice by business Message ID, not replayId. A Completed CPI execution alone does not confirm subscriber success.

11. Monitoring, alerts, and recovery

AreaWhat to monitor and recover
ERP sourceRetain committed invoice notifications, Message IDs, send attempts, and returned acknowledgements
SAP Integration Suite publisherMonitor message failures, lookup/login/publish errors, and uncertain results; arrange actual operational alerts
SKYVVA InterfaceSupplies event identity; this direct publisher does not create normal SKYVVA messages for monitoring or reprocessing
Salesforce subscriberIf using the example Flow, check activation, missing notices, and record-creation failures
Business reconciliationMatch ERP posted invoices to Invoice Notices by Message ID and invoice reference

Use CPI monitoring for this publisher; normal SKYVVA message monitoring/reprocessing is not created automatically. If a notice is missing, check the Flow's activation, event selection and record-creation errors. Reconcile uncertain publication before resending.

12. Summary

Configuration Summary

ComponentConfiguration
ReceiverSkyvva → Platform Event - Publishing
Integration / InterfaceERP Invoice Events / ERP Invoice Posted
EventERP_Invoice_Posted__e
FormatsERP input JSON; receiver request Application/XML; receiver response Application/JSON
Publication verificationCheck the publication acknowledgement
Subscriber verificationFind the Invoice Notice by Message ID (section 6.3)
Open this article in the interactive viewer →