I’m struggling to insert records into Airtable using VB.NET. My GET requests work perfectly, but POST operations keep failing with a 422 error. I think there might be an issue with my JSON formatting or request headers.
Here’s my current code:
Dim headers As WebHeaderCollection = New WebHeaderCollection()
headers.Clear()
headers.Add("Authorization: Bearer keyAbc123DefGHIJKL")
Dim apiUrl As String = "https://api.airtable.com/v0/appXyz789MnoQRS12/Records"
Dim request As HttpWebRequest = DirectCast(System.Net.HttpWebRequest.Create(apiUrl), HttpWebRequest)
request.ContentType = "application/json"
request.Headers = headers
request.Method = "POST"
request.Accept = "*/*"
Dim jsonPayload = "{""fields"": {""ProductName"": ""Sample Item"", ""Category"": ""Electronics"", ""Status"": ""Active""}}"
request.GetRequestStream.Write(System.Text.Encoding.UTF8.GetBytes(jsonPayload), 0, System.Text.Encoding.UTF8.GetBytes(jsonPayload).Count)
Dim response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
Dim result As String = ""
Using reader As New StreamReader(response.GetResponseStream())
result = reader.ReadToEnd()
End Using
MessageBox.Show(result)
I keep getting “422 Unprocessable Entity” error. What am I doing wrong with the request format?
I ran into this exact same issue last year when migrating some legacy VB.NET code to work with Airtable. The 422 error usually means your JSON structure is wrong.
The main problem is that Airtable expects a “records” array, not just “fields” directly. Your JSON should look like this:
Dim jsonPayload = "{""records"": [{""fields"": {""ProductName"": ""Sample Item"", ""Category"": ""Electronics"", ""Status"": ""Active""}}]}"
Also noticed you’re not closing your request stream properly. Add this line after writing your payload:
request.GetRequestStream().Close()
One more thing - wrap your response reading in a try-catch block. When I was debugging similar issues, the actual error details from Airtable were getting swallowed by the exception handler.
The records array structure is required even when you’re only inserting one record. Took me way too long to figure that out when I was working on our data sync tool.
Dealt with this same nightmare when connecting our warehouse system to Airtable last summer. The issue is likely your Authorization header format - you’re adding it with the colon included which can confuse the HTTP client. Change it to headers.Add(“Authorization”, “Bearer keyAbc123DefGHIJKL”) instead of including the colon in the string. That fixed about 80% of my 422 errors right there. Another gotcha is that Airtable is picky about the User-Agent header. Some API endpoints will reject requests without it. Add request.UserAgent = “YourAppName/1.0” before making the call. Also verify your base ID and table name are correct - I spent two days debugging what turned out to be a copy-paste error in my base identifier. The error response should give you specifics about what field validation failed, but make sure you’re actually reading the error stream when the exception occurs.
Encountered similar frustration when building a VB.NET integration for our project management workflow about six months ago. The 422 responses can be cryptic but there’s another angle worth checking - your API key permissions and base configuration. First verify your API key has write permissions to that specific table. I had cases where GET worked fine but POST failed because the key was read-only for certain tables. Log into your Airtable account and check the API key settings. Second issue I discovered was field type validation. Airtable enforces strict field types and your JSON values might not match what the base expects. If “Status” is configured as a single-select field in Airtable, the value “Active” must exactly match one of the predefined options including capitalization. Try logging the raw HTTP response body from your 422 error like this: vb Catch ex As WebException Using errorResponse = ex.Response.GetResponseStream() Using reader As New StreamReader(errorResponse) Console.WriteLine(reader.ReadToEnd()) End Using End Using End Try
The response usually contains specific field validation errors that point directly to the problem. Saved me countless hours of guessing.
Been wrestling with Airtable APIs for years now and that 422 is usually screaming about malformed requests. Your code has a stream handling issue that’s probably corrupting the payload.
Replace this mess:
request.GetRequestStream.Write(System.Text.Encoding.UTF8.GetBytes(jsonPayload), 0, System.Text.Encoding.UTF8.GetBytes(jsonPayload).Count)
With proper stream management:
Using stream As Stream = request.GetRequestStream()
Dim data As Byte() = Encoding.UTF8.GetBytes(jsonPayload)
stream.Write(data, 0, data.Length)
End Using
You’re converting the string to bytes twice which is wasteful and risky. The stream might not be getting flushed properly either.
Also your table name in the URL should probably be lowercase. I’ve seen Airtable throw 422s for incorrect resource paths. Try changing “Records” to “records” in your API endpoint.
One more thing - when debugging these API issues, always log the actual response body from the 422 error. Airtable gives pretty detailed error messages that tell you exactly what field or structure is wrong. Wrap your GetResponse call in a try-catch and read the error stream.
Had this exact headache a few months back when building an inventory sync tool. Beyond the JSON structure issue mentioned above, check your Content-Length header - VB.NET sometimes doesn’t set this automatically for POST requests. Try adding this before making the request: Dim payloadBytes() As Byte = System.Text.Encoding.UTF8.GetBytes(jsonPayload) request.ContentLength = payloadBytes.Length. Then use payloadBytes instead of converting the string again when writing to the stream. This solved intermittent 422 errors I was getting where the request body was being truncated. Also double-check your field names match exactly what’s in your Airtable base schema. Case sensitivity matters and I wasted hours troubleshooting what turned out to be a simple field name mismatch. The error response body usually contains specific details about which fields are causing issues, so make sure you’re reading that in your exception handling.