Some attachments on a note won't load via API, others do.

I list notes attached to an opportunity. In the list all attachments I added via the API work fine, but all attachments added by user directly in CRM appear to be missing filename, file ext etc. Opening them via the Sugar application works, but downloading via API gives me this error:

"{\"error\":\"not_found\",\"error_message\":\"The requested file Notes :: filename could not be found.\"}"

I am really annoyed by this.

What can I do?

Mind you it works for attachment that are present on the same opportunity which I added via the API.

This URL works for these attachments:

"{_baseUrlNew}/Notes/{noteId}/file/filename"

I also tried adding this based on the html inspection:

"{_baseUrlNew}/Notes/{noteId}/file/filename?force_download=1&1738746638522=1&platform=base"

Doesn't work

"{_baseUrlNew}/Notes/{noteId}/file?force_download=1"

Can anybody help?

  • Hello  , 

    Thanks for bringing this up!

    When a user creates a Note with an attachment and relates it to an Opportunity, SugarCRM actually creates two Note records in the database:

    1. The primary Note record, which contains the note’s details and is visible in the GUI.



    2. A secondary Note record, which is used solely to store the attached document. This record is not displayed in the list view but can be accessed if you retrieve its ID from the database.




    Based on your description, it sounds like you might be trying to fetch the image from the first Note record, which wouldn’t contain the file.

    Could you check if that’s the case? Let me know if this makes sense and if it helps point you in the right direction.

    Cheers,

    André

  • Hi, yes this was partly the problem. The documents added by the API got directly under the first node, but documents added via the user interface got a parent note. Documentation is very poor on this, but eventually I found this somewhere on the web. It is because in the past only 1 attachment per note was allowed, then they changed this and probably to keep compatibility they kept the old way of working to. So sometimes there is a child note in between, sometimes not.

    So now, when the filename is empty, i will go and find a note with that note_parent_id. It takes a lot more calls to the API, but I got it.

    Heres the code:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public async Task<List<Note>?> GetNotesForOpportunityAsync(string oppId, IMemoryCache cache)
    {
    try
    {
    string token = GetAccessTokenFromCache(cache);
    //string json = "{'$and':[{'parent_id':'" + oppId + "'},{'filename':{'$not_equals':''}}]}";
    string json = "{'parent_id':'" + oppId + "'}";
    JObject o = JObject.Parse(json);
    FilterBy f = new FilterBy()
    {
    Filter = new List<JObject>() { o },
    MaxNum = 10,
    };
    using APIHelper helper = new APIHelper() { Headers = new List<(string header, string headervalue)> { ("OAuth-Token", token) }, BaseURL = _baseUrlNew };
    var result = await helper.PostAsync<FilterResponse<Note>, FilterBy>("Notes/filter", f).ConfigureAwait(false);
    if (result.Records?.Count > 0)
    {
    List<Note> notes = new List<Note>();
    //for all records where the filename is empty, find notes based on note_parent_id
    foreach (var note in result.Records)
    {
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Hello  , 

    Is your goal to download all attachments from a given Opportunity id?

    I’d like to check if there’s an easier way to accomplish this.

    That said, I’m glad you found a solution that works! I’ll also share this insight with our knowledge team to review the documentation.

    Cheers,

    André

  • Yes, that's correct. If I get all notes for a given opportunity id, then I only get the top ones. If there is a nested note, I do not get it.