Search code examples
phplaravelguzzlefreshdesk

Freshdesk API Create note with attachment throwing validation error


use GuzzleHttp\Client;

function insert_freshdesk_note($ticketId, $content, $attachments=null)
{
    if(is_null($content)) {
        return false;
    }

    $url = 'https://mydomain.freshdesk.com/api/v2/tickets/'.$ticketId.'/notes';
    $method = 'POST';
    $userName = config('freshdesk_api_key');
    $password = 'password';

    $data = (!empty($attachments)) ? [
        "attachments[]" => $attachments,
        "body" => $content,
        "private" => false,
    ] : [
        "body" => $content,
        "private" => false,
    ];

    $options = (!empty($attachments)) ? [
        'json' => $data,
        'auth' => [$userName, $password],
        'headers' => ['content-type' => 'multipart/form-data']
    ] : [
        'json' => $data,
        'auth' => [$userName, $password]
    ];

    $client = new Client();

    try {
        $response = $client->request($method, $url, $options);
        return json_decode($response->getBody(), true);
    } catch (Exception $e) {
        Log::error($e);
    }
}

Above code is working fine without attachments but when an attachment comes into the picture it's throwing the following error:-

GuzzleHttp\Exception\ClientException: Client error: `POST https://mydomain.freshdesk.com/api/v2/tickets/13033/notes` resulted in a `400 Bad Request` response:
{"description":"Validation failed","errors":[{"field":"{\"attachments","message":"Unexpected/invalid field in request","

I am working according to the documentation and I have hit a dead end as of this point. I tried other permutations and combinations but via those, I wasn't able to resolve this problem.

Can anyone please help me. Here is the link of the documentation of freshdesk And in $attachments[] = '@/path/to/xyz.ext' this particular is going.

The function call will go like this:-

insert_freshdesk_note($this->freshdesk_ticket_id, $noteText, $image->image_full_path);

Solution

  • In the above question, I was trying to achieve the addition of note using GuzzleHTTP Client, Laravel Framework, and PHP language. Here's the following source code by which it starts working.

    use GuzzleHttp\Client;
    
    function insert_freshdesk_note($ticketId, $content, $attachments=null)
    {   
        if(is_null($content)) {
            return false;
        }
    
        $url = 'https://mydomain.freshdesk.com/api/v2/tickets/'.$ticketId.'/notes';
        $method = 'POST';
        $userName = config('freshdesk_api_key');
        $password = 'password';
    
        $attachmentsFilePath = explode('/',$attachments);
        $fileName = end($attachmentsFilePath);
    
        $options = (!empty($attachments)) ? [
            'multipart' => [
                [
                    'name'     => 'body',
                    'contents' => $content,
                ],
                [
                    'name'     => 'private',
                    'contents' => "false",
                ],
                [
                    'name'     => 'attachments[]',
                    'contents' => fopen($attachments, 'r'),
                    'filename' => $fileName,
                ],
            ],
            'auth' => [$userName, $password],
        ] : [
            'json' => [
                "body" => $content,
                "private" => false,
            ],
            'auth' => [$userName, $password]
        ];
    
        $client = new Client();
    
        try {
            $response = $client->request($method, $url, $options);
            return json_decode($response->getBody(), true);
        } catch (Exception $e) {
            Log::error($e);
        }
    }
    

    We have to send the data in multipart fashion in order to Freshdesk backend to understand that data is there, by writing multipart/form-type in the header won't help. If you look at documentation also with and without attachments below:-

    Without Attachment:-

    curl -v -u [email protected]:test -H "Content-Type: application/json" -X POST -d '{ "body":"Hi tom, Still Angry", "private":false, "notify_emails":["[email protected]"] }' 'https://domain.freshdesk.com/api/v2/tickets/3/notes'
    

    With Attachment:-

    curl -v -u [email protected]:test -F "attachments[]=@/path/to/attachment1.ext" -F "body=Hi tom, Still Angry" -F "notify_emails[][email protected]" -X POST 'https://domain.freshdesk.com/api/v2/tickets/20/notes'
    

    The difference in the curl can be seen. This was the missing piece that I overlooked.