Search code examples
c#apifacebook-graph-apicloudwhatsapp

Add a Template sample image to WhatsApp Cloud API


Good day

I am trying to create a template in C# with a media header using the WhatsApp cloud API as described here: Resumable Upload API. Now whenever I create the template an error is returned: File type not supported.

I have searched online for examples for other developers who experience the same but none found that resolved my issue. I have followed the suggestions/solutions in these two posts, but still bo luck:

My Steps:

  1. I create a session successfully.
  2. I use the sessionId returned to upload the media, also without issue.
  3. I then try to create the template with the handle returned (in step 2). This step returns the error File Type Not Supported.

Code:

Create session

// Create the session
var sessionId = "";
using (var httpClient = new HttpClient())
{
    using (var request = new HttpRequestMessage(new HttpMethod("POST"), $"https://graph.facebook.com/v14.0/{appId}/uploads"))
    {
        request.Headers.TryAddWithoutValidation("Authorization", "Bearer " + _accessToken);
        request.Headers.TryAddWithoutValidation("Content-Type", "application/json");

        request.Content = new StringContent("{\"file_length\":\"16384\",\"file_type\":\"image/png\",\"file_name\":\"test.png\"}");

        var response = await httpClient.SendAsync(request);
        var responseContent = response.Content.ReadAsStringAsync().Result;
        var result = System.Text.Json.JsonSerializer.Deserialize<SessionResponse>(responseContent);
        sessionId = result.id;
    }
}

Upload media

var handle = "";
var dataBinary =  System.IO.File.ReadAllBytes(@"C:\Temp\IMAGES\test.png");
using (var httpClient = new HttpClient())
{
    using (var request = new HttpRequestMessage(new HttpMethod("POST"), $"https://graph.facebook.com/v14.0/{sessionId}"))
    {
        request.Headers.TryAddWithoutValidation("Authorization", "OAuth " + _accessToken);
        request.Headers.TryAddWithoutValidation("file_offset", "0");
        request.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data");

        var multipartContent = new MultipartFormDataContent();
        multipartContent.Add(new ByteArrayContent(dataBinary));
        request.Content = multipartContent;

        var response = await httpClient.SendAsync(request);
        var responseContent = response.Content.ReadAsStringAsync().Result;
        var result = System.Text.Json.JsonSerializer.Deserialize<MediaUploadSessionResponse>(responseContent);
        handle = result.h;
    }
}

Create template

jsonData: (complete handle not added in this example)

{
    "name":"template_media",
    "components":[
       {
          "type":"HEADER",
          "format":"IMAGE",
          "example":{
             "header_handle":[
                "4:::ARaVEoRalHjf9hIFnYJb2O9I6BJeHNoonwkB...."
             ]
          }
       },
       {
          "type":"BODY",
          "text":"Please find media attached as requested."
       }
    ],
    "language":"en_US",
    "category":"TRANSACTIONAL"
 }

Request:

using (var httpClient = new HttpClient())
{
    using (var request = new HttpRequestMessage(new HttpMethod("POST"), $"https://graph.facebook.com/v14.0/{_businessAccountID}/message_templates"))
    {
        request.Headers.TryAddWithoutValidation("Authorization", "Bearer " + _accessToken);

        request.Content = new StringContent(jsonData);
        request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

        var response = await httpClient.SendAsync(request);
        var responseContent = response.Content.ReadAsStringAsync().Result;
    }
}

Error Returned (File Type Not Supported):

{
    "error": {
        "message": "Invalid parameter",
        "type": "OAuthException",
        "code": 100,
        "error_subcode": 2388084,
        "is_transient": false,
        "error_user_title": "File Type Not Supported",
        "error_user_msg": "The type of file is not supported.",
        "fbtrace_id": "AZalksSZjALNaBLXiiJzgZw"
    }
}

Please help, thank you.


Solution

  • I found the solution, hope this helps others with the same issue.

    Instead of adding the "Content-Type" headers to the request I added them on request.Content, for example: request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

    I also changed the MultipartFormDataContent to a ByteArrayContent with the content header application/x-www-form-urlencoded.

    See below for a full code example that worked for me.

    Create the session

    var sessionId = "";
    using (var httpClient = new HttpClient())
    {
        using (var request = new HttpRequestMessage(new HttpMethod("POST"), $"https://graph.facebook.com/v14.0/{appId}/uploads"))
        {
            request.Headers.TryAddWithoutValidation("Authorization", "Bearer " + _accessToken);
            
            request.Content = new StringContent("{\"file_length\":\"16384\",\"file_type\":\"image/png\",\"file_name\":\"test.png\"}");
            request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
    
            var response = await httpClient.SendAsync(request);
            if (!response.IsSuccessStatusCode)
                return null;
    
            var responseContent = response.Content.ReadAsStringAsync().Result;
            var result = System.Text.Json.JsonSerializer.Deserialize<SessionResponse>(responseContent);
            sessionId = result.id;
        }
    }
    

    Upload media

    var handle = "";
    var dataBinary =  System.IO.File.ReadAllBytes(@"C:\Temp\IMAGES\test.png");
    using (var httpClient = new HttpClient())
    {
        using (var request = new HttpRequestMessage(new HttpMethod("POST"), $"https://graph.facebook.com/v14.0/{sessionId}"))
        {
            request.Headers.TryAddWithoutValidation("Authorization", "OAuth " + _accessToken);
            request.Headers.TryAddWithoutValidation("file_offset", "0");
    
           request.Content = new ByteArrayContent(dataBinary);
           request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
    
            var response = await httpClient.SendAsync(request);
            if (!response.IsSuccessStatusCode)
                return null;
    
            var responseContent = response.Content.ReadAsStringAsync().Result;
            var result = System.Text.Json.JsonSerializer.Deserialize<MediaUploadSessionResponse>(responseContent);
            handle = result.h;
        }
    }
    

    Create template

    jsonData: (complete handle not added in this example)

    {
        "name":"template_media",
        "components":[
           {
              "type":"HEADER",
              "format":"IMAGE",
              "example":{
                 "header_handle":[
                    "4:::ARaVEoRalHjf9hIFnYJb2O9I6BJeHNoonwkB...."
                 ]
              }
           },
           {
              "type":"BODY",
              "text":"Please find media attached as requested."
           }
        ],
        "language":"en_US",
        "category":"TRANSACTIONAL"
     }
    

    Request

    var responseContent = string.empty;
    
    using (var httpClient = new HttpClient())
    {
        using (var request = new HttpRequestMessage(new HttpMethod("POST"), $"https://graph.facebook.com/v14.0/{_businessAccountID}/message_templates"))
        {
            request.Headers.TryAddWithoutValidation("Authorization", "Bearer " + _accessToken);
    
            request.Content = new StringContent(jsonData);
            request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
    
            var response = await httpClient.SendAsync(request);
            if (!response.IsSuccessStatusCode)
                return null;
    
            responseContent = response.Content.ReadAsStringAsync().Result;
        }
    }