How to add emails to contact lists in SendGrid with Node?

Viewed 899

I'm working on a React Native app with Firebase Functions. I am unable to add new contacts to a SendGrid list consistently.

This is my function:

 exports.addToSendGridMembersList = functions.https.onCall(async (data) => {
  const {first, last, email} = data
  p(first,last,email)

  const axios = require('axios');

  let e = JSON.stringify(email)
  let f =  JSON.stringify(first)
  let l = JSON.stringify(last)

  p("JSON.stringify: ", e, f, l)

  axios({
    method: "PUT",
    url: "https://api.sendgrid.com/v3/marketing/contacts",
    headers: 
    { 'content-type': 'application/json',
      authorization: 'Bearer ' + SEND_GRID_KEY },
    body: 
      { "list_ids": [ 
        "eda0bc01-b098-4366-ad58-8bab03ec9b33" 
      ],
      "contacts": [
        {
          "email": "o@gmail.com",
          "first_name": "o",
          "last_name": "o"
        }
      ]
    }
  })
    .then(function (error, response, body) {
      console.log(error)
      console.log(response)
      console.log(body);
    })
});

I at first thought the axios body was unable to read constants that's why I stringified them and was going to insert them in the body (first, last and email) values. This is the response I get in Google Cloud logs

JSON.stringify: "gg@gmail.com" "gg" "gg"
> Unhandled error { Error: Request failed with status code 400 at createError (/workspace/node_modules/axios/lib/core/createError.js:16:15) at settle (/workspace/node_modules/axios/lib/core/settle.js:17:12) at IncomingMessage.handleStreamEnd (/workspace/node_modules/axios/lib/adapters/http.js:260:11) at IncomingMessage.emit (events.js:203:15) at IncomingMessage.EventEmitter.emit (domain.js:466:23) at endReadableNT (_stream_readable.js:1145:12) at process._tickCallback (internal/process/next_tick.js:63:19) config: { url: 'https://api.sendgrid.com/v3/marketing/contacts', method: 'put', headers: { Accept: 'application/json, text/plain, */*', 'Content-Type': 'application/json', authorization: 'Bearer HIDDEN', 'User-Agent': 'axios/0.21.1' }, transformRequest: [ [Function: transformRequest] ], transformResponse: [ [Function: transformResponse] ], timeout: 0, adapter: [Function: httpAdapter], xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, validateStatus: [Function: validateStatus], body: { list_ids: [Array], contacts: [Array] }, data: undefined }, request: ClientRequest { domain: Domain { domain: null, _events: [Object], _eventsCount: 3, _maxListeners: undefined, members: [], [Symbol(kWeak)]: WeakReference {} }, _events: [Object: null prototype] { socket: [Function], abort: [Function], aborted: [Function], connect: [Function], error: [Function], timeout: [Function], prefinish: [Function: requestOnPrefinish] }, _eventsCount: 7, _maxListeners: undefined, output: [], outputEncodings: [], outputCallbacks: [], outputSize: 0, writable: true, _last: true, chunkedEncoding: false, shouldKeepAlive: false, useChunkedEncodingByDefault: true, sendDate: false, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, socket: TLSSocket { _tlsOptions: [Object], _secureEstablished: true, _securePending: false, _newSessionPending: false, _controlReleased: true, _SNICallback: null, servername: 'api.sendgrid.com', alpnProtocol: false, authorized: true, authorizationError: null, encrypted: true, _events: [Object], _eventsCount: 9, connecting: false, _hadError: false, _handle: [TLSWrap], _parent: null, _host: 'api.sendgrid.com', _readableState: [ReadableState], readable: true, domain: [Domain], _maxListeners: undefined, _writableState: [WritableState], writable: false, allowHalfOpen: false, _sockname: null, _pendingData: null, _pendingEncoding: '', server: undefined, _server: null, ssl: [TLSWrap], _requestCert: true, _rejectUnauthorized: true, parser: null, _httpMessage: [Circular], [Symbol(res)]: [TLSWrap], [Symbol(asyncId)]: 81, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0, [Symbol(connect-options)]: [Object] }, connection: TLSSocket { _tlsOptions: [Object], _secureEstablished: true, _securePending: false, _newSessionPending: false, _controlReleased: true, _SNICallback: null, servername: 'api.sendgrid.com', alpnProtocol: false, authorized: true, authorizationError: null, encrypted: true, _events: [Object], _eventsCount: 9, connecting: false, _hadError: false, _handle: [TLSWrap], _parent: null, _host: 'api.sendgrid.com', _readableState: [ReadableState], readable: true, domain: [Domain], _maxListeners: undefined, _writableState: [WritableState], writable: false, allowHalfOpen: false, _sockname: null, _pendingData: null, _pendingEncoding: '', server: undefined, _server: null, ssl: [TLSWrap], _requestCert: true, _rejectUnauthorized: true, parser: null, _httpMessage: [Circular], [Symbol(res)]: [TLSWrap], [Symbol(asyncId)]: 81, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0, [Symbol(connect-options)]: [Object] }, _header: 'PUT /v3/marketing/contacts HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/json\r\nauthorization: Bearer HIDDEN\r\nUser-Agent: axios/0.21.1\r\nHost: api.sendgrid.com\r\nConnection: close\r\nContent-Length: 0\r\n\r\n', _onPendingData: [Function: noopPendingOutput], agent: Agent { domain: null, _events: [Object], _eventsCount: 1, _maxListeners: undefined, defaultPort: 443, protocol: 'https:', options: [Object], requests: {}, sockets: [Object], freeSockets: {}, keepAliveMsecs: 1000, keepAlive: false, maxSockets: Infinity, maxFreeSockets: 256, maxCachedSessions: 100, _sessionCache: [Object] }, socketPath: undefined, timeout: undefined, method: 'PUT', insecureHTTPParser: undefined, path: '/v3/marketing/contacts', _ended: true, res: IncomingMessage { _readableState: [ReadableState], readable: false, domain: [Domain], _events: [Object], _eventsCount: 3, _maxListeners: undefined, socket: [TLSSocket], connection: [TLSSocket], httpVersionMajor: 1, httpVersionMinor: 1, httpVersion: '1.1', complete: true, headers: [Object], rawHeaders: [Array], trailers: {}, rawTrailers: [], aborted: false, upgrade: false, url: '', method: null, statusCode: 400, statusMessage: 'Bad Request', client: [TLSSocket], _consuming: false, _dumped: false, req: [Circular], responseUrl: 'https://api.sendgrid.com/v3/marketing/contacts', redirects: [] }, aborted: undefined, timeoutCb: null, upgradeOrConnect: false, parser: null, maxHeadersCount: null, _redirectable: Writable { _writableState: [WritableState], writable: true, domain: [Domain], _events: [Object], _eventsCount: 2, _maxListeners: undefined, _options: [Object], _ended: true, _ending: true, _redirectCount: 0, _redirects: [], _requestBodyLength: 0, _requestBodyBuffers: [], _onNativeResponse: [Function], _currentRequest: [Circular], _currentUrl: 'https://api.sendgrid.com/v3/marketing/contacts' }, [Symbol(isCorked)]: false, [Symbol(outHeadersKey)]: [Object: null prototype] { accept: [Array], 'content-type': [Array], authorization: [Array], 'user-agent': [Array], host: [Array] } }, response: { status: 400, statusText: 'Bad Request', headers: { server: 'nginx', date: 'Mon, 28 Dec 2020 01:39:11 GMT', 'content-type': 'application/json', 'content-length': '50', connection: 'close', 'x-amzn-requestid': '7cec2ea8-620a-4096-af97-c58c3f5f12d2', 'access-control-allow-origin': '*', 'access-control-allow-headers': 'AUTHORIZATION, Content-Type, On-behalf-of, x-sg-elas-acl, X-Recaptcha, X-Request-Source', 'x-amz-apigw-id': 'YPWR7E1GvHcFVXg=', 'access-control-allow-methods': 'PUT,DELETE,OPTIONS', 'access-control-expose-headers': 'Link, Location', 'x-amzn-trace-id': 'Root=1-5fe9373f-69accb7255a34e6321797cf3;Sampled=0', 'x-envoy-upstream-service-time': '93', 'referrer-policy': 'strict-origin-when-cross-origin', 'x-content-type-options': 'nosniff', 'x-ratelimit-limit': '200', 'x-ratelimit-remaining': '199', 'x-ratelimit-reset': '49' }, config: { url: 'https://api.sendgrid.com/v3/marketing/contacts', method: 'put', headers: [Object], transformRequest: [Array], transformResponse: [Array], timeout: 0, adapter: [Function: httpAdapter], xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, validateStatus: [Function: validateStatus], body: [Object], data: undefined }, request: ClientRequest { domain: [Domain], _events: [Object], _eventsCount: 7, _maxListeners: undefined, output: [], outputEncodings: [], outputCallbacks: [], outputSize: 0, writable: true, _last: true, chunkedEncoding: false, shouldKeepAlive: false, useChunkedEncodingByDefault: true, sendDate: false, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, socket: [TLSSocket], connection: [TLSSocket], _header: 'PUT /v3/marketing/contacts HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/json\r\nauthorization: Bearer HIDDEN\r\nUser-Agent: axios/0.21.1\r\nHost: api.sendgrid.com\r\nConnection: close\r\nContent-Length: 0\r\n\r\n', _onPendingData: [Function: noopPendingOutput], agent: [Agent], socketPath: undefined, timeout: undefined, method: 'PUT', insecureHTTPParser: undefined, path: '/v3/marketing/contacts', _ended: true, res: [IncomingMessage], aborted: undefined, timeoutCb: null, upgradeOrConnect: false, parser: null, maxHeadersCount: null, _redirectable: [Writable], [Symbol(isCorked)]: false, [Symbol(outHeadersKey)]: [Object] }, data: { errors: [Array] } }, isAxiosError: true, toJSON: [Function: toJSON] }
1 Answers

Turns out axios was failing. I switched to request and it worked like a charm. Here's my final code:

var request = require("request");
  var options = { method: 'PUT',
    url: 'https://api.sendgrid.com/v3/marketing/contacts',
    headers: 
    { 'content-type': 'application/json',
      authorization: 'Bearer ' + SEND_GRID_KEY},
    body: 
    { list_ids: [ 'eda0bc01-b098-4366-ad58-8bab03ec9b33' ],
      contacts: [
        {
          "email": e,
          "first_name": f,
          "last_name": l
        }
      ]
    },
    json: true };

  request(options, function (error, response, body) {
    if (error) throw new Error(error);

    console.log(body);
  });

You can test out SendGrid's api and generate code here: https://sendgrid.api-docs.io/v3.0/contacts/add-or-update-a-contact

Related