Search code examples
sendgridsendgrid-api-v3

SendGrid: "batch id not found"


I'm playing around with the v3 API and trying to demo the concept of scheduling emails and then cancelling them. Here is what I did:

  • Created a batch with POST https://api.sendgrid.com/v3/mail/batch and got batch a batch ID
  • Did a mail send with POST https://api.sendgrid.com/v3/mail/send and included that batch ID as the batch_id parameter and put in a future send_at time
  • Attempted to pass that batch ID into POST https://api.sendgrid.com/v3/user/scheduled_sends/:batch_id

However the latter call fails as 404 Not Found with "message": "batch id not found". In fact it would seem that however many batch IDs I create, attempting to update them always yields this not-found message. The result is, the scheduled send cannot be cancelled, and the email sends at the appointed time. I should add that attempting to GET /v3/mail/batch/{batch_id} returns an empty array [].

Am I doing something wrong here?? Is this a limitation of the free account perhaps?

EDIT: I'm going to add some raw details to show what I am doing. I am doing these in Postman but I will export in cURL syntax to demonstrate.

First I create a batch:

curl --location --request POST 'https://api.sendgrid.com/v3/mail/batch' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <token redacted>' \
--data-raw ''

Response: {"batch_id":"OWU0NzgxYzUtMjkzZS0xMWVkLTg5NDAtYWUyMDAwNjVjZGU0LTZiODk2MDliZA"}

So now the next thing I want to try is to verify that batch ID:

curl --location --request GET 'https://api.sendgrid.com/v3/user/scheduled_sends/OWU0NzgxYzUtMjkzZS0xMWVkLTg5NDAtYWUyMDAwNjVjZGU0LTZiODk2MDliZA' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <token redacted>'

The response is, oddly, a 200 OK with just [] which doesn't seem right does it? I created a batch and it has an ID, so why can't I verify its existence?

Documentation here states: https://docs.sendgrid.com/api-reference/cancel-scheduled-sends/validate-batch-id

When you pass a valid batch_id to this endpoint, it will return a 200 status code and the batch ID itself.

If you pass an invalid batch_id to the endpoint, you will receive a 400 level status code and an error message.

A batch_id does not need to be assigned to a scheduled send to be considered valid. A successful response means only that the batch_id has been created, but it does not indicate that it has been associated with a send.

Interestingly if I put any arbitrary string in that URL instead of a batch ID, I also get a 200 OK with empty array. I cannot even reproduce what the document is saying about receiving a 400 error for an invalid ID.

However if I take it on faith that the batch WAS created, I would go ahead and try to send an email with it:

curl --location --request POST 'https://api.sendgrid.com/v3/mail/send' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token redacted>' \
--data-raw '{
    "batch_id": "OWU0NzgxYzUtMjkzZS0xMWVkLTg5NDAtYWUyMDAwNjVjZGU0LTZiODk2MDliZA",
    "send_at": 1661969713,
    "personalizations": [{
        "to": [{
                "email": "thatemail@mycompany.com",
                "name": "John Doe"
            }
        ]
    }],
    "from": {
        "email": "myemail@mycompany.com",
        "name": "Jane Doe"
    },
    "reply_to": {
        "email": "customer_service@example.com",
        "name": "Example Customer Service Team"
    },
    "subject": "Example Email 6",
    "content": [{
            "type": "text/html",
            "value": "<p>Test email!</p><p>%open-track%</p>"
        }
    ],
    "custom_args":{
        "sf-id": "some-arbitrary-id6",
        "sf-org-id": "some-arbitrary-org-id"
    },
    "mail_settings": {
        "sandbox_mode": {
            "enable": false
        }
    },
    "tracking_settings": {
        "click_tracking": {
            "enable": true,
            "enable_text": false
        },
        "open_tracking": {
            "enable": true,
            "substitution_tag": "%open-track%"
        },
        "subscription_tracking": {
            "enable": false
        }
    }
}
'

At the time of writing that timestamp is for 3h from now, resolving at 2:15PM August 31st Eastern Time. I send that call and get 202 Accepted.

Then, finally, I attempt to pause the batch.

curl --location --request PATCH 'https://api.sendgrid.com/v3/user/scheduled_sends/OWU0NzgxYzUtMjkzZS0xMWVkLTg5NDAtYWUyMDAwNjVjZGU0LTZiODk2MDliZA' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <token redacted>' \
--data-raw '{"status": "pause"}'

My response is a 404 NOT FOUND with:

{
    "errors": [
        {
            "field": null,
            "message": "batch id not found"
        }
    ]
}

So... what is going on here???


Solution

  • So a few things:

    • It turns out I was missing a step here. The first time I want to put in a pause or cancel on a batch, I actually need to POST /v3/user/scheduled_sends/ with batch_id in the request body. I was trying PATCH. Strange behaviour here as the batch ID already exists, but OK.
    • After my first successful test of this, the entire behaviour of the GET /v3/mail/batch/{batch_id} API changed for me. I am no longer able to reproduce getting back an empty array. Every response is either a success with the batch ID or a fail.

    I don't know why these behaviours changed, but they did. There may be some quirk in which fresh accounts that have never paused/cancelled a batch simply do not have a functional "validate batch" call. Now that I have done a successful pause for the first time, the behaviour of GET /v3/mail/batch/{batch_id} finally matches the documentation.