Embedding Conga Sign into Salesforce Using Public REST APIs or from Salesforce Object button on UI
This guide provides a step-by-step API integration flow for embedding Conga Sign on Advantage Platform functionality into Salesforce, offering more flexibility than the standard Conga Sign managed package. Ideal for:
Custom Lightning Web Components
Enhanced user experiences
Automated document flows
Tailored button actions on Salesforce records
Embedding Options
Option 1: Using Conga Sign Public Rest APIs
Full programmatic control
Supports background delivery, tagging, dynamic roles
Option 2: Using Salesforce Object Button
Launches embedded signing experience via a pre-configured button on Opportunity, Account, etc.
Prerequisites
Before you begin, ensure you have completed the following:
- A RLS Conga Org with Conga Sign onboarded.
An Integration User Client Id and Secret if you are using API flow not the UI flow. You can create Integration User from Admin > Users > Add User. Select the User Type Integration. The Users Client Id and Secret is presented on this screen.
A Data Sync connection Connected in RLS Conga UI, Document Management App > Conga Sign Settings > Data Sync Connection with a Salesforce Administrator User. (Make sure that this user does not frequently login to Salesforce).
Data Mapping setup for fields that needs to be synced back to Salesforce. Currently it supports the following Data Types fields to be synced: Email, Checkbox, Number, Phone, URL, Text, TextArea, TextArea (Long), TextArea (Rich)
login-hostdomain (Targeted env where RLS Org and Conga Sign has been onboarded) → https://login-rlsprod.congacloud.com
hostdomain (Targeted env where RLS Org and Conga Sign has been onboarded) → https://prod-rls10.congacloud.com
API Integration Flow
Step 1: Obtain Access Token
Use OAuth 2.0 to get a token from Conga's Identity Provider.
OAuth Token Request (Client Credentials Grant)
Post https://<login-hostdomain>/api/v1/auth/connect/tokenContent-Type: applicatoin/x-www-form-urlencodedclient_id=<integration_user_client_id>
client_secret=<integration_user_client_secret>
grant_type=client_credentials
scope=signSample cURL Request: curl --location 'https://<login-hostdomain>/api/v1/auth/connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=your_client_id' \
--data-urlencode 'client_secret=your_client_secret' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=sign'Response Example: {
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ...abc",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "sign"
}Notes
access_token should be used in all subsequent API requests in the Authorization header as: Authorization: Bearer <access_token>Token lifetime is typically 3600 seconds (1 hour).This flow is ideal for server-to-server integrations (e.g., from Apex, middleware, or backend services).
Apex Token Request using Named Credentials
How to perform the OAuth token request from Apex using the Http class in Salesforce:
Step 1: Setup Named Credential in Salesforce
Go to Setup > Named Credentials.
Click New Named Credential
Fill in:
Label:
CongaTokenCredentialName:
CongaTokenCredentialURL:
https://<login-hostdomain>← Do not include/api/v1/auth/connect/tokenIdentity Type: Named Principal
Authentication Protocol: OAuth 2.0
Authentication Flow: Select existing or create a new one with:
Scope: sign
Client ID / Secret
Token endpoint:
https://<login-hostdomain>/api/v1/auth/connect/token
Click Save.
public class CongaAuthServiceNamed {
public class TokenResponse {
public String access_token;
public String token_type;
public Integer expires_in;
public String scope;
}
public static String getAccessToken() {
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:CongaTokenCredential/api/v1/auth/connect/token');
req.setMethod('POST');
req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
req.setBody('grant_type=client_credentials&scope=sign');
Http http = new Http();
HttpResponse res = http.send(req);
if (res.getStatusCode() == 200) {
TokenResponse token = (TokenResponse) JSON.deserialize(res.getBody(), TokenResponse.class);
return token.access_token;
} else {
System.debug('Failed Token Response: ' + res.getBody());
throw new CalloutException('Unable to retrieve token: ' + res.getStatus());
}
}
}Usage Example: String token = CongaAuthServiceNamed.getAccessToken();
System.debug('Access Token (Named Cred): ' + token);Create a Transaction (Envelope)
POST https://<hostdomain>/api/signconnector/v1/transaction | Header | Value |
|---|---|
Authorization | Bearer {access_token} |
Content-Type | application/json |
idp | Salesforce or SalesforceSandbox |
| Field | Type | Required | Description |
|---|---|---|---|
iDP | string | Yes | Identity provider value (e.g., "SalesforceSandbox" or "Salesforce") |
senderEmail | string | Yes | Email of the sender (must be authenticated in the system) |
iDPRecordId | string | Yes | Salesforce record ID (e.g., Opportunity ID) |
iDPOrgId | string | Yes | Salesforce Org ID |
iDPRecordType | string | Yes | API name of the Salesforce record (e.g., Opportunity) |
iDPRecordName | string or null | No | Optional name of the Salesforce record |
templateId | string or null | No | Optional Template ID used for signing |
transactionName | string | Yes | Friendly name for the transaction |
documentIds | string or null | No | Optional Comma-separated list of document IDs |
recipientIds | string or null | No | Comma-separated Salesforce IDs (Contact, User, or Lead only). Used only if recipients is not present |
recipients | array of objects | No | Recipient model (has priority over recipientIds) |
isBackgroundMode | boolean | Yes | Whether the transaction is run in background.
|
deliveryMethod | string | Yes (If isBackgroundMode=true) | "email" or "URL" |
routingType | string | Yes | "parallel" or "sequential" |
{
"Id": "0033C00000h1szNQAQ"
}| Field | Required | Notes |
|---|---|---|
Id | Yes | Must be a valid Salesforce Contact, Lead, or User ID |
Email | No | Ignored if Id is present |
FirstName | No | Ignored if Id is present |
LastName | No | Ignored if Id is present |
Id){
"Email": "user@example.com",
"FirstName": "John",
"LastName": "Doe"
}| Field | Required | Notes |
|---|---|---|
Id | No | Must not be present |
Email | Yes | Must be a valid email |
FirstName | Yes | First name of the recipient |
LastName | Yes | Last name of the recipient |
Id and personal info:{
"Id": "0033C00000h1szNQAQ",
"Email": "test@example.com",
"FirstName": "Test",
"LastName": "User"
}It will pick Id from this combination and ignore the Email, FirstName and LastName values and create a recipient based on the Id value provided. {
"Email": "test@example.com"
}This is not allowed, and must include FirstName and LastName when Id is not used. | Condition | Required Fields |
|---|---|
| If Id is present | Only Id |
| If Id is not present | Email, FirstName, LastName |
| If both Id and others are present | Invalid. |
| Rule | Description |
|---|---|
| Precedence | If recipients is provided, it is used. recipientIds is ignored. |
recipientIds | Must only contain valid Salesforce Contact, User, or Lead IDs. |
| Background mode rules: | |
If isBackgroundMode = true | Then deliveryMethod is required ("email" or "URL"). |
If deliveryMethod = "URL" | Only one recipient is allowed (in recipients or recipientIds). |
signingUrl will be returned only if deliveryMethod = "URL" and recipient count = 1 | |
tagUrl | Only present if isBackgroundMode = false |
redirectUrl | Only present if isBackgroundMode = true |
{
"iDP": "SalesforceSandbox",
"senderEmail": "qaconnectoruser+1@0ymyfvtv.mailosaur.net",
"iDPRecordId": "006Dy00000CrepjIAB",
"iDPOrgId": "00D3C0000005LKJUA2",
"iDPRecordType": "Opportunity",
"iDPRecordName": "PB Connector Test",
"templateId": "X6kh51Sc--tZwLahEITF3UlMqyk=",
"transactionName": "PB Connector Test - Transaction",
"documentIds": "0693C000002JrkmQAC",
"recipientIds": "0033C00000h1szNQAQ, 0053C000006OoUHQA0",
"recipients": [
{
"Id": "0033C00000h1szNQAQ",
"Email": "basket-rapidly@0ymyfvtv.mailosaur.net",
"FirstName": "test",
"LastName": "user"
},
{
"Email": "ankit@0ymyfvtv.mailosaur.net",
"FirstName": "ankit",
"LastName": "new"
},
{
"Email": "conred@0ymyfvtv.mailosaur.net",
"FirstName": "conred",
"LastName": "s"
},
{
"Email": "prathik@0ymyfvtv.mailosaur.net",
"FirstName": "prathik",
"LastName": "b"
}
],
"isBackgroundMode": true,
"deliveryMethod": "email",
"routingType": "parallel"
}Successful Transaction Creation Response{
"success": true,
"packageId": "EF_9efM4Ec_UA9CfxRUjTK4vQ_E=",
"errors": [],
"redirectUrl": "", // present if backgroundMode = true and deliveryMethod = URL
"tagUrl": "", // present if backgroundMode = false
"signingUrl": "" // present if backgroundMode = true AND deliveryMethod = URL AND only 1 recipient
}| Field | Type | Description |
|---|---|---|
success | boolean | Indicates whether the transaction was created successfully. true means the operation succeeded. |
packageId | string | Unique identifier of the generated signing package. Used for tracking and signing operations. |
errors | array | Any validation or system errors encountered. Empty array means no issues. |
redirectUrl | string | (Optional) A URL to redirect the sender or signer post-transaction creation. Empty if not applicable. Present only if isBackgroundMode = true |
tagUrl | string | URL for the sender to view/edit the tag positions in the document (used for preparing the signing flow). Present only if isBackgroundMode = false |
signingUrl | string | Present only if:
|
Usage Tips
Use
tagUrlfor the sender to access the document in tag-edit mode (typically pre-sending).Use
packageIdto:Query the transaction status later
Generate signing URLs
Audit trail or logging
signingUrlmight be blank in this response if:Signing URLs are generated per-recipient later
Additional preparation is required (e.g., signing order)
If
success: false,errorswill contain detailed messages (e.g., invalid IDs, missing documents).
| isBackgroundMode | deliveryMethod | recipient count | redirectUrl | tagUrl | signingUrl |
|---|---|---|---|---|---|
| true | URL | 1 | Yes | No | Yes |
| true | URL | >1 | Yes | No | No |
| false | (any) | any | No | Yes | No |
{
"success": true,
"packageId": "abc123",
"errors": [],
"redirectUrl": "<salesforce org recirect url of the record from where transaction
intiated>",
"tagUrl": "",
"signingUrl": "<signing url to sign the document for that specific recipient>"
}Example 2: Background Mode with Multiple Recipients{
"success": true,
"packageId": "abc123",
"errors": [],
"redirectUrl": "<salesforce org recirect url of the record from where transaction
intiated>",
"tagUrl": "",
"signingUrl": ""
}Example 3: Interactive (Non-background) Mode{
"success": true,
"packageId": "abc123",
"errors": [],
"redirectUrl": "",
"tagUrl": "<tag url to edit the transaction like add/edit the documents or
add/edit the recipients or add/edit Signature or other recipient tags on the
document>",
"signingUrl": ""
}
APEX Example for Create transactionpublic class CongaSignService {
public static void createTransaction(String accessToken) {
String endpoint = 'https://rls-dev.congacloud.io/api/signconnector/v1/transaction';
Map<String, Object> payload = new Map<String, Object>{
'iDP' => 'SalesforceSandbox',
'senderEmail' => 'qaconnectoruser+1@0ymyfvtv.mailosaur.net',
'iDPRecordId' => '006Dy00000CrepjIAB',
'iDPOrgId' => '00D3C0000005LKJUA2',
'iDPRecordType' => 'Opportunity',
'iDPRecordName' => 'PB Connector Test',
'templateId' => 'X6kh51Sc--tZwLahEITF3UlMqyk=',
'transactionName' => 'PB Connector Test - Transaction',
'documentIds' => '0693C000002JrkmQAC',
'isBackgroundMode' => true,
'deliveryMethod' => 'email',
'routingType' => 'parallel',
'recipients' => new List<Map<String, Object>>{
new Map<String,Object>{
'Id' => '0033C00000h1szNQAQ',
'Email' => 'basket-rapidly@0ymyfvtv.mailosaur.net',
'FirstName' => 'test',
'LastName' => 'user'
},
new Map<String,Object>{
'Email' => 'ankit@0ymyfvtv.mailosaur.net',
'FirstName' => 'ankit',
'LastName' => 'new'
},
new Map<String,Object>{
'Email' => 'conred@0ymyfvtv.mailosaur.net',
'FirstName' => 'conred',
'LastName' => 's'
},
new Map<String,Object>{
'Email' => 'prathik@0ymyfvtv.mailosaur.net',
'FirstName' => 'prathik',
'LastName' => 'b'
}
}
};
String jsonPayload = JSON.serialize(payload);
Http http = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint(endpoint);
req.setMethod('POST');
req.setHeader('Authorization', 'Bearer ' + accessToken);
req.setHeader('Content-Type', 'application/json');
req.setHeader('idp', 'SalesforceSandbox');
req.setBody(jsonPayload);
HttpResponse res = http.send(req);
if (res.getStatusCode() == 200 || res.getStatusCode() == 201) {
System.debug('Transaction created successfully: ' + res.getBody());
} else {
System.debug('Transaction creation failed. Status: ' + res.getStatusCode() + ', Body: ' + res.getBody());
}
}
}
public class CongaSignIntegration {
public static void runCongaSignFlow() {
String token = CongaSignAuthService.getAccessToken();
if (token != null) {
CongaSignService.createTransaction(token);
} else {
System.debug('Could not obtain access token. Aborting transaction creation.');
}
}
}Call
CongaSignIntegration.runCongaSignFlow()to perform the entire flow.Replace
your_client_id_hereandyour_client_secret_herewith your actual Conga OAuth credentials.Replace all placeholder URLs (
<hostdomain>) with your actual Conga host domain.
Generate the Signing URL
To embed the signing experience within Salesforce, retrieve the embedded signing URL.
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer token (Bearer <ACCESS_TOKEN>) used for authentication |
| Parameter | Description |
|---|---|
packageId | Unique identifier of the CS package (e.g., ySIWGx6WYY1Lk5L-pBjDbcnyZm0=) |
roleId | UUID of the recipient role in the package (e.g., 5a58c13e-34bd-4cfa-b970-33ec0cfbbdf1) |
GET https://<hostdomain>/api/sign/v1/cs-packages/<package_id>/roles/<role_id>/signingUrl
Authorization: Bearer {access_token}
Expected Response"https://<hostdomain>/sign/?&packageId=<package_id>&signerId=<signer_id>&linkURL=https://sandbox.esignlive.com/authentication?target=https%3A%2F%2Fsandbox.esignlive.com%2Ftransaction%2FySIWGx6WYY1Lk5L-pBjDbcnyZm0%3D%2Fsign&loginToken=UU5JeEFGVzdsYWpiODlRS2VFbWZYaFIwUVFaYVBuK2lKYjlFVUxlRThxRFErZm1vVW16cjMzMTRMcnkzNStNaXRvajhLYnRUK1R0aExleUVOZEh2WlFVcjlNdlFET0NwZjArK1o1TCs4L2ZJaWEvcHhEM0pLcXU3VXFYUTAxODFSYVBZMGl3bGc1YmJHdkJIMFlLelJWSTRSVWRoUlc1UlJHNXJWMUpKWkhJeFpFZDFUV1ExV205eGRGUjJZMU5XVVdGblpHVldNRmd3T0VGNlJHRndSblZFTlZkSmFtUlpNMGx3WW01R1IwOExoYWgwOXJXQnFrTnlFK29VQlM5bktFVVVPTloyWTRha2U5aEkzLzl3c2c9PQ%3D%3D"Embed the Signing Experience in Salesforce
<template>
<iframe src={signingUrl} width="100%" height="600px" frameborder="0"></iframe>
</template>
import { LightningElement, api } from 'lwc';
export default class CongaSignEmbed extends LightningElement {
@api signingUrl;
}
Option B: Visualforce Page<apex:page>
<iframe src="{!signingUrl}" width="100%" height="600px" frameborder="0"/>
</apex:page>
Monitor and Complete the Transaction
After you create a transaction (envelope), you want to monitor its status — whether it's still in progress, completed, signed, or declined.
How to Monitor Transaction Status
GET https://<hostdomain>/api/signconnector/v1/transaction/{package_id}
Authorization: Bearer {access_token}
Content-Type: application/jsonExample Response{
"congaOrgId": "55debe94-f9c8-49d4-8447-158bda7781ac",
"idp": "salesforcesandbox",
"packageId": "IUHDptsAlqWZlp-m0IZ54MxuIGk=",
"senderEmail": "ankit-connector@qpljleto.mailosaur.net",
"idpRecordId": "006Dy00000Cw6r6",
"idpRecordType": "opportunity",
"finalDocumentSyncStatus": "Pending",
"finalDocumentSyncErrorDescription": "",
"writebackStatus": "Pending",
"writebackDescription": null,
"writebackErrorDescription": "",
"packageStatus": "In Progress",
"packageRecipients": "SignConnector RLS Dev, Ankit ContactMailasour",
"packageCompletedOn": null,
"packageDueDate": null,
"packageLastUpdated": "2025-05-28T05:54:24Z",
"id": "93ac5b03-bcb5-4c3d-a690-664b3956123f",
"name": "Test Opp",
"createdBy": {
"id": "246b73fc-10a4-904b-dbc3-833c096a620e",
"name": "SignConnector RLS Dev"
},
"createdDate": "2025-05-28T11:24:24.823",
"modifiedBy": {
"id": "246b73fc-10a4-904b-dbc3-833c096a620e",
"name": "SignConnector RLS Dev"
},
"modifiedDate": "2025-06-09T13:55:59.587",
"externalId": null,
"eTag": "1d97062a-7cbb-4c71-9788-85a168204e6a",
"IDPInstanceUrl": null
}Response Fields Explained| Field | Description |
|---|---|
congaOrgId | Unique identifier for your Conga Org. |
idp | Identity provider used (e.g. salesforce, salesforcesandbox). |
packageId | The unique identifier of the transaction (a.k.a. package/envelope). |
senderEmail | Email of the sender who initiated the transaction. |
idpRecordId | Salesforce object record ID (e.g. Opportunity/Lead/Contact/User). |
idpRecordType | Type of Salesforce record linked to the transaction (e.g., opportunity). |
finalDocumentSyncStatus | Status of syncing the final signed document back to Salesforce (Pending, Success, Failed). |
finalDocumentSyncErrorDescription | Describes any error that occurred during final document sync, if applicable. |
writebackStatus | Status of metadata or field writeback to Salesforce (Pending, Success, Failed). |
writebackDescription | Human-readable description of the writeback status (optional). |
writebackErrorDescription | Describes any error that occurred during writeback, if applicable. |
packageStatus | Current status of the signing package (In Progress, Completed, Cancelled, etc.). |
packageRecipients | A comma-separated list of recipients in the transaction. |
packageCompletedOn | Timestamp when the transaction was fully completed (null if not completed). |
packageDueDate | Due date for the transaction to be completed (if set). |
packageLastUpdated | Last updated timestamp of the transaction. |
id | Internal ID of the transaction record in Conga Sign's system. |
name | Name of the transaction (e.g., from transactionName field in the creation call). |
createdBy | Object with id and name of the user who created the transaction. |
createdDate | Date and time when the transaction was created. |
modifiedBy | Object with id and name of the last user who modified the transaction. |
modifiedDate | Timestamp of the most recent update. |
externalId | Any external identifier passed in (can be used for cross-system mapping). |
eTag | Internal versioning tag for concurrency handling (optimistic locking). |
IDPInstanceUrl | URL of the Salesforce org or environment associated with this transaction (if needed for callbacks or sync). |
packageStatus == "Completed"→ Trigger post-processing or document sync.finalDocumentSyncStatus == "Failed"→ Retry logic or alerting.Monitor
packageLastUpdatedandpackageCompletedOnfor audit trail.
Launch Sign via Salesforce Object Button
This method allows Salesforce users to initiate a Conga Sign transaction directly from standard or custom Salesforce object detail pages (e.g., Opportunity, Account) using a Custom Detail Page Button.
Use this option when you want a no-code, user-friendly way to send documents for signature using predefined templates or without template you want to send transaction using Salesforce contact/lead or user id and send documents which is stored in Salesforce content document record, directly from a Salesforce record (e.g., Opportunity).
Step-by-Step Setup
1. Create a Custom Button on the Salesforce Object
Object: Opportunity (or any other object like Account, Contact)
Button Type: Detail Page Button
Behavior: Display in existing window without sidebar or header
Content Source: URL
2. Button Configuration Example
| Field | Value |
|---|---|
| Label | Send with Sign |
| Name | Send_with_Sign |
| Object Name | Opportunity |
| Behavior | Display in existing window without sidebar or header |
| Display Type | Detail Page Button |
| Content Source | URL |
| Link Encoding | Unicode (UTF-8) |
https://<hostdomain>/sign-connector/createtransaction?
idp=SalesforceSandbox
&idporgid=00D3C0000005LKJUA2
&idprecordid={!Opportunity.Id}
&idprecordtype=Opportunity
&transactionname={!Opportunity.Name}
&templateid=xHcju8PtxUkCsLZBLtrOw2IEAhg=
&recipient1=0033C00000hjYXVQA2
&recipient2=003Dy000010bDcM
&documentids=0693C0000028HMNQA2
&isbackgroundmode=false
&backgrounddelivery=email
&routingType=parallelReplace the values like templateid, recipient1, documentids (comma seperated list for maximum 10 documents) etc., as needed.
You can pass multiple recipients by appending &recipient2=..., &recipient3=... up to recipient20, etc.
How it Works:
It opens the RLS UI if you aren't logged in already. Then it will bring the Login screen where you select either Salesforce or Salesforce Sandbox. Once selected, you will be auto logged in to RLS Org.
Opens an embedded or full-screen experience for sending the document using the specified template or without template where documents or recipients can be added and tagging screen for signature tags.
Additional Notes
isbackgroundmode=falseindicates that the user will interact manually with the flow.If
isbackgroundmode=true, it triggers a silent/automated delivery, and you must passdeliveryMethod=urlfor embedded signing. if this is true then transaction will automatically sent in the background and user will bring back to salesforce record page.You can use merge fields like
!Opportunity.Name,!Opportunity.Id,!Account.Id, etc., to dynamically inject context.User can also view all existing transactions created from specific salesforce record using below configuration.
Option: View Sign Transactions from Salesforce Objects
This custom Detail Page Button allows Salesforce users to view all sign transactions related to a specific record (e.g., Opportunity) directly within a new browser window.
Use Case: Use this button to provide users with a quick overview of all Conga Sign transactions associated with a specific Salesforce record, such as an Opportunity.
| Field | Value |
|---|---|
| Label | View Sign Transactions |
| Name | View_Sign_Transactions |
| Object Name | Opportunity |
| Behavior | Display in new window |
| Display Type | Detail Page Button |
| Link Encoding | Unicode (UTF-8) |
| Content Source | URL |
https://<hostdomain>/sign-connector/viewtransactions?
idp=SalesforceSandbox
&idprecordid={!Opportunity.Id}
&idprecordtype=OpportunityWindow Options| Setting | Value |
|---|---|
| Height | 600 |
| Width | [Optional] |
| Show Scrollbars | Checked |
| Resizable | Checked |
| Show Address Bar | Not Checked |
| Show Toolbars | Not Checked |
| Show Menu Bar | Not Checked |
| Show Status Bar | Not Checked |
| Window Position | No Preference |
This URL filters the transactions based on:
idp: The Salesforce environment (SalesforceSandboxorSalesforce)idprecordid: The current record's ID (e.g.,Opportunity.Id)idprecordtype: The object type (e.g.,Opportunity)
The Conga Sign web UI will open in a new window showing all relevant transactions for the record.
