title: HTTP POST 400 Error with Strapi and Sendgrid
body: <p>I am doing a udemy course and with it has a part where you can automatically send a confirmation e-mail once the user has submitted their details on the checkout form using strapi/sendgrid.</p>
  
  <p>When I hit submit, all the data gets sent correctly, although an error message comes up and no e-mail is sent. The pop up box says [Object, object] and in the console the error message looks like this:</p>
  
  <pre><code>data: [{messages: [{id: "Auth.form.error.email.invalid"}]}]
  0: {messages: [{id: "Auth.form.error.email.invalid"}]}
  error: "Bad Request"
  message: [{messages: [{id: "Auth.form.error.email.invalid"}]}]
  0: {messages: [{id: "Auth.form.error.email.invalid"}]}
  statusCode: 400 
  </code></pre>
  
  <p>My checkout component looks like this:</p>
  
  <pre><code>import React from "react";
  // prettier-ignore
  import { Container, Box, Button, Heading, Text, TextField, Modal, Spinner } from "gestalt";
  // prettier-ignore
  import { Elements, StripeProvider, CardElement, injectStripe } from 'react-stripe-elements';
  import ToastMessage from "./ToastMessage";
  import { getCart, calculatePrice, clearCart, calculateAmount } from "../utils";
  import { withRouter } from "react-router-dom";
  import Strapi from "strapi-sdk-javascript/build/main";
  const apiUrl = process.env.API_URL || "http://localhost:8082";
  const strapi = new Strapi(apiUrl);
  
  class _CheckoutForm extends React.Component {
    state = {
      cartItems: [],
      address: "",
      postalCode: "",
      city: "",
      confirmationEmailAddress: "",
      toast: false,
      toastMessage: "",
      orderProcessing: false,
      modal: false
    };
  
    componentDidMount() {
      this.setState({ cartItems: getCart() });
    }
  
    handleChange = ({ event, value }) =&gt; {
      event.persist();
      this.setState({ [event.target.name]: value });
    };
  
    handleConfirmOrder = async event =&gt; {
      event.preventDefault();
  
      if (this.isFormEmpty(this.state)) {
        this.showToast("Fill in all fields");
        return;
      }
  
      this.setState({ modal: true });
    };
  
    handleSubmitOrder = async () =&gt; {
      const {
        cartItems,
        city,
        address,
        postalCode,
        confirmationEmailAddress
      } = this.state;
  
      const amount = calculateAmount(cartItems);
      // Process order
      this.setState({ orderProcessing: true });
      let token;
      try {
        const response = await this.props.stripe.createToken();
        token = response.token.id;
        await strapi.createEntry("orders", {
          amount,
          brews: cartItems,
          city,
          postalCode,
          address,
          token
        });
        await strapi.request("POST", "/email", {
          data: {
            to: confirmationEmailAddress,
            subject: `Order Confirmation - BrewHaha ${new Date(Date.now())}`,
            text: "Your order has been processed",
            html: "&lt;bold&gt;Expect your order to arrive in 2-3 shipping days&lt;/bold&gt;"
          }
        });
        this.setState({ orderProcessing: false, modal: false });
        clearCart();
        this.showToast("Your order has been successfully submitted!", true);
      } catch (err) {
        this.setState({ orderProcessing: false, modal: false });
        this.showToast(err.message);
      }
    };
  
    isFormEmpty = ({ address, postalCode, city, confirmationEmailAddress }) =&gt; {
      return !address || !postalCode || !city || !confirmationEmailAddress;
    };
  
    showToast = (toastMessage, redirect = false) =&gt; {
      this.setState({ toast: true, toastMessage });
      setTimeout(
        () =&gt;
          this.setState(
            { toast: false, toastMessage: "" },
            // if true passed to 'redirect' argument, redirect home
            () =&gt; redirect &amp;&amp; this.props.history.push("/")
          ),
        5000
      );
    };
  
    closeModal = () =&gt; this.setState({ modal: false });
  
    render() {
      // prettier-ignore
      const { toast, toastMessage, cartItems, modal, orderProcessing } = this.state;
  
      return (
        &lt;Container&gt;
          &lt;Box
            color="darkWash"
            margin={4}
            padding={4}
            shape="rounded"
            display="flex"
            justifyContent="center"
            alignItems="center"
            direction="column"
          &gt;
            {/* Checkout Form Heading */}
            &lt;Heading color="midnight"&gt;Checkout&lt;/Heading&gt;
            {cartItems.length &gt; 0 ? (
              &lt;React.Fragment&gt;
                {/* User Cart */}
                &lt;Box
                  display="flex"
                  justifyContent="center"
                  alignItems="center"
                  direction="column"
                  marginTop={2}
                  marginBottom={6}
                &gt;
                  &lt;Text color="darkGray" italic&gt;
                    {cartItems.length} Items for Checkout
                  &lt;/Text&gt;
                  &lt;Box padding={2}&gt;
                    {cartItems.map(item =&gt; (
                      &lt;Box key={item._id} padding={1}&gt;
                        &lt;Text color="midnight"&gt;
                          {item.name} x {item.quantity} - $
                          {item.quantity * item.price}
                        &lt;/Text&gt;
                      &lt;/Box&gt;
                    ))}
                  &lt;/Box&gt;
                  &lt;Text bold&gt;Total Amount: {calculatePrice(cartItems)}&lt;/Text&gt;
                &lt;/Box&gt;
                {/* Checkout Form */}
                &lt;form
                  style={{
                    display: "inlineBlock",
                    textAlign: "center",
                    maxWidth: 450
                  }}
                  onSubmit={this.handleConfirmOrder}
                &gt;
                  {/* Shipping Address Input */}
                  &lt;TextField
                    id="address"
                    type="text"
                    name="address"
                    placeholder="Shipping Address"
                    onChange={this.handleChange}
                  /&gt;
                  {/* Postal Code Input */}
                  &lt;TextField
                    id="postalCode"
                    type="text"
                    name="postalCode"
                    placeholder="Postal Code"
                    onChange={this.handleChange}
                  /&gt;
                  {/* City Input */}
                  &lt;TextField
                    id="city"
                    type="text"
                    name="city"
                    placeholder="City of Residence"
                    onChange={this.handleChange}
                  /&gt;
                  {/* Confirmation Email Address Input */}
                  &lt;TextField
                    id="confirmationEmailAddress"
                    type="email"
                    name="confirmationEmailAddress"
                    placeholder="Confirmation Email Address"
                    onChange={this.handleChange}
                  /&gt;
                  {/* Credit Card Element */}
                  &lt;CardElement
                    id="stripe__input"
                    onReady={input =&gt; input.focus()}
                  /&gt;
                  &lt;button id="stripe__button" type="submit"&gt;
                    Submit
                  &lt;/button&gt;
                &lt;/form&gt;
              &lt;/React.Fragment&gt;
            ) : (
              // Default Text if No Items in Cart
              &lt;Box color="darkWash" shape="rounded" padding={4}&gt;
                &lt;Heading align="center" color="watermelon" size="xs"&gt;
                  Your Cart is Empty
                &lt;/Heading&gt;
                &lt;Text align="center" italic color="green"&gt;
                  Add some brews!
                &lt;/Text&gt;
              &lt;/Box&gt;
            )}
          &lt;/Box&gt;
          {/* Confirmation Modal */}
          {modal &amp;&amp; (
            &lt;ConfirmationModal
              orderProcessing={orderProcessing}
              cartItems={cartItems}
              closeModal={this.closeModal}
              handleSubmitOrder={this.handleSubmitOrder}
            /&gt;
          )}
          &lt;ToastMessage show={toast} message={toastMessage} /&gt;
        &lt;/Container&gt;
      );
    }
  }
  
  const ConfirmationModal = ({
    orderProcessing,
    cartItems,
    closeModal,
    handleSubmitOrder
  }) =&gt; (
    &lt;Modal
      accessibilityCloseLabel="close"
      accessibilityModalLabel="Confirm Your Order"
      heading="Confirm Your Order"
      onDismiss={closeModal}
      footer={
        &lt;Box
          display="flex"
          marginRight={-1}
          marginLeft={-1}
          justifyContent="center"
        &gt;
          &lt;Box padding={1}&gt;
            &lt;Button
              size="lg"
              color="red"
              text="Submit"
              disabled={orderProcessing}
              onClick={handleSubmitOrder}
            /&gt;
          &lt;/Box&gt;
          &lt;Box padding={1}&gt;
            &lt;Button
              size="lg"
              text="Cancel"
              disabled={orderProcessing}
              onClick={closeModal}
            /&gt;
          &lt;/Box&gt;
        &lt;/Box&gt;
      }
      role="alertdialog"
      size="sm"
    &gt;
      {/* Order Summary */}
      {!orderProcessing &amp;&amp; (
        &lt;Box
          display="flex"
          justifyContent="center"
          alignItems="center"
          direction="column"
          padding={2}
          color="lightWash"
        &gt;
          {cartItems.map(item =&gt; (
            &lt;Box key={item._id} padding={1}&gt;
              &lt;Text size="lg" color="red"&gt;
                {item.name} x {item.quantity} - ${item.quantity * item.price}
              &lt;/Text&gt;
            &lt;/Box&gt;
          ))}
          &lt;Box paddingY={2}&gt;
            &lt;Text size="lg" bold&gt;
              Total: {calculatePrice(cartItems)}
            &lt;/Text&gt;
          &lt;/Box&gt;
        &lt;/Box&gt;
      )}
  
      {/* Order Processing Spinner */}
      &lt;Spinner
        show={orderProcessing}
        accessibilityLabel="Order Processing Spinner"
      /&gt;
      {orderProcessing &amp;&amp; (
        &lt;Text align="center" italic&gt;
          Submitting Order...
        &lt;/Text&gt;
      )}
    &lt;/Modal&gt;
  );
  
  const CheckoutForm = withRouter(injectStripe(_CheckoutForm));
  
  const Checkout = () =&gt; (
    &lt;StripeProvider apiKey="pk_test_F92R0PypgxxkAKVgMt7pH3Og00RQXrWC3T"&gt;
      &lt;Elements&gt;
        &lt;CheckoutForm /&gt;
      &lt;/Elements&gt;
    &lt;/StripeProvider&gt;
  );
  
  export default Checkout;
  </code></pre>
  
  <p>My e-mail controller .js file looks like this:</p>
  
  <pre><code>'use strict';
  
  /**
   * Email.js controller
   *
   * @description: A set of functions called "actions" of the `email` plugin.
   */
  
  const _ = require('lodash');
  
  module.exports = {
    send: async ctx =&gt; {
      // Retrieve provider configuration.
      const config = await strapi
        .store({
          environment: strapi.config.environment,
          type: 'plugin',
          name: 'email',
        })
        .get({ key: 'provider' });
  
      // Verify if the file email is enable.
      if (config.enabled === false) {
        strapi.log.error('Email is disabled');
        return ctx.badRequest(null, [
          {
            messages: [
              { id: 'Email.status.disabled', message: 'Emails disabled' },
            ],
          },
        ]);
      }
  
      // Something is wrong
      if (ctx.status === 400) {
        return;
      }
  
      let options = ctx.request.body;
  
      // await strapi.plugins.email.services.email.send(options, config);
      try {
        // Send email to the user
        await strapi.plugins["email"].services.email.send({
          to: options.to,
          from: "test@example.com",
          subject: options.subject,
          text: options.text,
          html: options.html
        });
      } catch (err) {
        return ctx.badRequest(null, err);
      }
  
  
      // Send 200 `ok`
      ctx.send({});
    },
  
    getEnvironments: async ctx =&gt; {
      const environments = _.map(
        _.keys(strapi.config.environments),
        environment =&gt; {
          return {
            name: environment,
            active: strapi.config.environment === environment,
          };
        }
      );
  
      ctx.send({ environments });
    },
  
    getSettings: async ctx =&gt; {
      let config = await strapi.plugins.email.services.email.getProviderConfig(
        ctx.params.environment
      );
  
      ctx.send({
        providers: strapi.plugins.email.config.providers,
        config,
      });
    },
  
    updateSettings: async ctx =&gt; {
      await strapi
        .store({
          environment: ctx.params.environment,
          type: 'plugin',
          name: 'email',
        })
        .set({ key: 'provider', value: ctx.request.body });
  
      ctx.send({ ok: true });
    },
  };
  </code></pre>
  
  <p>I also have the correct API key from sendgrid in my strapi sendgrid e-mail settings.</p>
  
  <p>Questions seem to take up to 6 months to get answered on the course, so a faster solution would be greatly appreciated.</p>
  
  <p>Happy to provide more code if needed.</p>
  
  <p>Thank you</p>