Airtable API API in Go
Airtable API API in Go
This guide shows you how to integrate the Airtable API into your Go application. Spreadsheet-database hybrid API with CRUD on bases, records, and attachments.
Prerequisites
- Go installed on your system
- An Airtable API API key (sign up at https://airtable.com/developers/web/api)
- Basic familiarity with HTTP APIs
Installation
go mod init myapp
go get github.com/go-resty/resty/v2
Basic Usage
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
apiKey := os.Getenv("API_KEY")
if apiKey == "" {
apiKey = "YOUR_API_KEY"
}
baseURL := "https://api.airtable.com"
req, _ := http.NewRequest("GET", baseURL+"/v1/resources", nil)
req.Header.Set("Authorization", "Bearer "+apiKey)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println("Status:", resp.Status)
fmt.Println(string(body))
}
Error Handling
package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
func callAPIWithRetry(url, apiKey string, maxRetries int) ([]byte, error) {
var lastErr error
for attempt := 0; attempt < maxRetries; attempt++ {
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer "+apiKey)
resp, err := http.DefaultClient.Do(req)
if err != nil {
lastErr = err
time.Sleep(time.Duration(1<<attempt) * time.Second)
continue
}
if resp.StatusCode == 429 {
retryAfter := resp.Header.Get("Retry-After")
fmt.Println("Rate limited. Retry-After:", retryAfter)
resp.Body.Close()
time.Sleep(60 * time.Second)
continue
}
if resp.StatusCode >= 400 {
body, _ := io.ReadAll(resp.Body)
resp.Body.Close()
lastErr = fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body))
time.Sleep(time.Duration(1<<attempt) * time.Second)
continue
}
body, err := io.ReadAll(resp.Body)
resp.Body.Close()
return body, err
}
return nil, lastErr
}
func main() {
apiKey := os.Getenv("API_KEY")
body, err := callAPIWithRetry("https://api.airtable.com/v1/resources", apiKey, 3)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(string(body))
}
Advanced Usage
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"time"
)
type AirtableClient struct {
APIKey string
BaseURL string
HTTP *http.Client
}
func NewClient(apiKey, baseURL string) *AirtableClient {
return &AirtableClient{
APIKey: apiKey,
BaseURL: baseURL,
HTTP: &http.Client{Timeout: 30 * time.Second},
}
}
func (c *AirtableClient) do(method, path string, body interface{}) ([]byte, error) {
var reqBody io.Reader
if body != nil {
jsonData, _ := json.Marshal(body)
reqBody = bytes.NewBuffer(jsonData)
}
req, _ := http.NewRequest(method, c.BaseURL+path, reqBody)
req.Header.Set("Authorization", "Bearer "+c.APIKey)
req.Header.Set("Content-Type", "application/json")
resp, err := c.HTTP.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}
func (c *AirtableClient) ListResources() ([]byte, error) {
return c.do("GET", "/v1/resources", nil)
}
func (c *AirtableClient) CreateResource(data map[string]interface{}) ([]byte, error) {
return c.do("POST", "/v1/resources", data)
}
func main() {
client := NewClient(os.Getenv("API_KEY"), "https://api.airtable.com")
resources, err := client.ListResources()
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(string(resources))
}
Best Practices
- Store your API key in an environment variable, never in source code
- Implement retry logic with exponential backoff for 429 and 5xx errors
- Set reasonable timeouts (10-30 seconds) for all API calls
- Log request IDs from response headers for debugging
- Cache responses where appropriate to reduce API calls