web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Microsoft Dynamics 365 | Integration, Dataverse...
Answered

WEB-API Request to create a quote based on an opportunity

(0) ShareShare
ReportReport
Posted on by 10

HI everbody,

I am trying to find what I need in a web request so that I can create a fresh quote based on an existing opportunity.
The goal is to have several information taken from the opportunity into the quote (like Account, Contact, Currency, ...)

There is an SDK - I know - but I need a way to do this without the SDK. For testing purposes I am using Postman.

Here is the Request that I am currently using:

URL:


POST {{URLTOCRM/api/data/v9.1/quotes?$select=quoteid}}

BODY:

{
    "quotenumber": "ZYY-Q21-00141",
    "totalamount": 0,
    "opportunityid@odata.bind": "/opportunities(71dfe9e9-a3ee-eb11-bacb-0022487ef2a3)"
}
 
As a result I get a new quote that has the opportunity linked. But no other information was transfered from the opportunity to the quote:
pastedimage1627381218008v1.png

I have the same question (0)
  • Verified answer
    Sergi Valero Profile Picture
    145 on at

    Hello Jeo!!

    In order to add more information to your new quote, you need to add the other properties into the body of your request.

    If you want to add the account and contact associated with your opportunity, you need to indicate the account id and contact id. If your opportunity is already linked to the opportunity, you can simply get the values from there through the executionContext of the opportunity (not sure you can get them using Postman), here is an example:

    Postman Body: 

    {
        "quotenumber": "ZYY-Q21-00141",
        "totalamount": 0,
        "opportunityid@odata.bind": "/opportunities(71dfe9e9-a3ee-eb11-bacb-0022487ef2a3)"
        "customerid@odata.bind": "/accounts(accountid)"
    }
     Where accountid is the id of the associated account.

    Javascript web resource:

    function createQuote (executionContext) {
        const formContext = executionContext.getFormContext();
        const opportunityId = formContext.data.entity.getId().slice(1,-1);
        const accountId = formContext.getAttribute(accountField).getValue();
        const contactId = formContext.getAttribute(contactField).getValue();
        
        const parameters = {
            quotenumber: "ZYY-Q21-00141",
            totalamount: 0,
            opportunityid@odata.bind: "/opportunities("   opportunityId   ")",
            accountid@odata.bind: "/accounts("   accountId   ")",
            contactid@odata.bind: "/contacts("   contactId   ")"
        }
        Request("POST", formContext.context.getClientUrl()   '/api/data/v9.2/quotes', parameters);
    }
    
    function Request (action, uri, parameters) {
        const data = parameters || {};
        return new Promise(function (resolve, reject) {  
            var request = new XMLHttpRequest();   
            request.open(action, uri, true);  
            request.setRequestHeader("OData-MaxVersion", "4.0");  
            request.setRequestHeader("OData-Version", "4.0");  
            request.setRequestHeader("Accept", "application/json");  
            request.setRequestHeader("Content-Type", "application/json; charset=utf-8");  
            request.setRequestHeader("Prefer", "odata.maxpagesize=100");  
     
            request.onreadystatechange = function () {  
                if (this.readyState === 4) {  
                    request.onreadystatechange = null;  
                    switch (this.status) {  
                        case 200: // Success with content returned in response body.  
                        case 204: // Success with no content returned in response body.  
                            resolve(this);  
                            break;  
                        default: // All other statuses are unexpected so are treated like errors.  
                            var error;  
                            try {  
                                error = JSON.parse(request.response).error;  
                            } catch (e) {  
                                error = new Error("Unexpected Error");  
                            }  
                            reject(error);  
                            break;  
                    }  
                }  
            };  
            request.send(JSON.stringify(data));  
        });
    }

    Note that the fields' name I used are an example, make sure to replace them with the name of your fields before using the code

    For additional information:

    MS Dataverse Web API

    Request Function Source

    @odata.bind documentation

  • Jeo Profile Picture
    10 on at

    Thank you. So there is no easy way to just say "here is the opportunity, please get all the info from there" like you can do using the frontend ?!

    Many thanks for the detailed answer. It is solvable like that I think. I just thought there would be an easier way.

  • Sergi Valero Profile Picture
    145 on at

    Hey Jeo!

    Not 100% sure there isn't an easier way to do it. The easiest way I know and how I always do this is by creating a web resource, passing the execution context and work from there with the Web API.

  • Verified answer
    meelamri Profile Picture
    13,216 User Group Leader on at

    Hi, 

    You can use the standard action: "GenerateQuoteFromOpportunity": https://docs.microsoft.com/en-us/dynamics365/customer-engagement/web-api/generatequotefromopportunity?view=dynamics-ce-odata-9

    This action has a parameter that allows you to define the columns to copy from the opportunity. Please refer to my sample code below: 

     

    var parameters = {};
    parameters.OpportunityId = "289756E6-F2EA-EB11-BACB-000D3A4AF872";
    //allColumns...
    parameters.ColumnSet = {
            "AllColumns": true
    }
    
    var req = new XMLHttpRequest();
    req.open("POST", Xrm.Page.context.getClientUrl()   "/api/data/v9.1/GenerateQuoteFromOpportunity", true);
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("OData-Version", "4.0");
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.onreadystatechange = function() {
        if (this.readyState === 4) {
            req.onreadystatechange = null;
            if (this.status === 200) {
                var results = JSON.parse(this.response);
            } else {
                Xrm.Utility.alertDialog(this.statusText);
            }
        }
    };
    req.send(JSON.stringify(parameters));

  • Jeo Profile Picture
    10 on at

    I'll try that. It looks exactly like what I was hoping for

  • meelamri Profile Picture
    13,216 User Group Leader on at

    Don't hesitate to give feedback if it doesn't work on your environment, good luck !

  • Jeo Profile Picture
    10 on at

    Excellent answer, everything works as expected. I does exactly what I was looking for. Thank you again!

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > Microsoft Dynamics 365 | Integration, Dataverse, and general topics

#1
Siv Sagar Profile Picture

Siv Sagar 93 Super User 2025 Season 2

#2
#ManoVerse Profile Picture

#ManoVerse 76

#3
Martin Dráb Profile Picture

Martin Dráb 64 Most Valuable Professional

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans