The developers'

API Guide

Everything you need to know about building, purchasing and integrating with APIs.

REST APIs

What is a REST (Representational State Transfer) API?

A REST API is an application programming interface that adheres to the principles of representational state transfer, a software architectural style for distributed systems. REST APIs are used for web services, allowing for interaction with RESTful web services using standard HTTP methods. They take advantage of existing protocols and focus on the interaction between client and server in a networked environment.

Over the last two decades, REST has become an extremely popular tool for building software applications to the point where it now includes a vast, rich ecosystem of developer tools. A survey from Rapid API determined that two-thirds of developers expect to increase their usage of REST APIs in 2020, and more than 80% of developers are either using REST in production, building a proof of concept with REST, or investigating REST for a production service. REST is highly versatile and can help develop software faster, more efficiently, and scalable.

REST API examples

Node.js

Ruby

Python

Java

Curl

Response

import 'dotenv/config'
import Nylas from 'nylas'

const NylasConfig = {
  apiKey: process.env.NYLAS_API_KEY,
  apiUri: process.env.NYLAS_API_URI,
}

const nylas = new Nylas(NylasConfig)

async function fetchRecentThreads() {
  try {
    const identifier = process.env.NYLAS_GRANT_ID
    const threads = await nylas.threads.list({
      identifier,
      queryParams: {
        limit: 5,
      }
    })

    console.log('Recent Threads:', threads)
  } catch (error) {
    console.error('Error fetching threads:', error)
  }
}

fetchRecentThreads()
require 'nylas'

nylas = Nylas::Client.new(api_key: "<NYLAS_API_KEY_OR_ACCESS_TOKEN>")
query_params = { limit: 5 }
threads, _ = nylas.threads.list(identifier: "<NYLAS_GRANT_ID>", query_params: query_params)

threads.map.with_index { |thread, i|
    puts("Thread #{i}")
    participants = thread[:participants]

    participants.each{ |participant|
        puts(
            "Subject: #{thread[:subject]} | "\
            "Participant: #{participant[:name]} | "\
            "Email: #{participant[:email]}"
        )
    }
}
from dotenv import load_dotenv
load_dotenv()

import os
import sys
from nylas import Client

nylas = Client(
    os.environ.get('NYLAS_API_KEY'),
    os.environ.get('NYLAS_API_URI')
)

grant_id = os.environ.get("NYLAS_GRANT_ID")

threads = nylas.threads.list(
  grant_id,
  query_params={
    "limit": 5
  }
)

print(threads) 
import com.nylas.NylasClient;
import com.nylas.models.*;
import com.nylas.models.Thread;

public class ReadThreadParameters {
    public static void main(String[] args) 
    throws NylasSdkTimeoutError, NylasApiError {

        NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();

        ListThreadsQueryParams queryParams = 
        new ListThreadsQueryParams.Builder().
        limit(5).
        build();

        ListResponse<Thread> threads = nylas.threads().list("<NYLAS_GRANT_ID>", 
        queryParams);

        int index = 0;
        for(Thread thread : threads.getData()){
            System.out.printf("%s ", index);
            List<EmailName> participants = thread.getParticipants();
            assert participants != null;
            for(EmailName participant : participants){
                System.out.printf("  Subject: %s | Participant: %s | Email: %s%n",
                        thread.getSubject(),
                        participant.getName(),
                        participant.getEmail());
            }
            index++;
        }
    }
}
curl --request GET \
  --url https://api.us.nylas.com/v3/grants/<GRANT_ID>/threads
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY_OR_ACCESS_TOKEN>' \
  --header 'Content-Type: application/json'
{
  "request_id": "cbd60372-df33-41d3-b203-169ad5e3AAAA",
  "data": [{
  "grant_id": "ca8f1733-6063-40cc-a2e3-ec7274abef11",
  "id": "7ml84jdmfnw20sq59f30hirhe",  // The thread's ID.
  "object": "thread",
  "has_attachments": false,
  "has_drafts": false,
  "earliest_message_date": 1634149514,
  "latest_message_received_date": 1634832749,
  "latest_message_sent_date": 1635174399,
  "participants": [
    {
      "email": "renee.smith@example.com",
      "name": "Renee Smith"
    },
    {
      "email": "rebecca.crumpler@example.com",
      "name": "Rebecca Lee Crumpler"
    }
  ],
  "snippet": "jnlnnn --Sent with Nylas",
  "starred": false,
  "subject": "Dinner Wednesday?",
  "unread": false,
  "message_ids": [  // A list of IDs for all messages in the thread.
    "njeb79kFFzli09",
    "998abue3mGH4sk"
  ],
  "draft_ids": [  // A list of IDs for all drafts in the thread.
    "a809kmmoW90Dx"
  ],
  "folders": [  // A list of folders that messages in the thread are associated with.
    "8l6c4d11y1p4dm4fxj52whyr9",
    "d9zkcr2tljpu3m4qpj7l2hbr0"
  ],
  "latest_draft_or_message": {
    "body": "Hello, I just sent a message using Nylas!",
    "date": 1635355739,
    "attachments": {
      "content": "YXR0YWNoDQoNCi0tLS0tLS0tLS0gRm9yd2FyZGVkIG1lc3NhZ2UgL=",
      "content_type": "text/calendar",
      "id": "4kj2jrcoj9ve5j9yxqz5cuv98",  // The attachment's ID.
      "size": 1708,
      "content_type": "application/ics",
      "filename": "invite.ics",
      "id": "70jcsv367jaiavt4njeu4xswg",  // The attachment's ID.
      "size": 1708
    },
    "folders": {  // A list of folders the latest message in the thread is associated with.
      "8l6c4d11y1p4dm4fxj52whyr9",
      "d9zkcr2tljpu3m4qpj7l2hbr0"
    },
    "from": {
      "name": "Renee Smith",
      "email": "renee.smith@example.com"
    },
    "grant_id": "41009df5-bf11-4c97-aa18-b285b5f2e386",
    "id": "njeb79kFFzli09",  // The message ID for the latest message in the thread.
    "object": "message",
    "reply_to": {
      "name": "Renee Smith",
      "email": "renee.smith@example.com"
    },
    "snippet": "Hello, I just sent a message using Nylas!",
    "starred": true,
    "subject": "Hello From Nylas!",
    "thread_id": "1t8tv3890q4vgmwq6pmdwm8qgsaer",  // The thread's ID.
    "to": {
      "name": "Geoff Dale",
      "email": "geoff.dale@example.com"
    },
    "unread": true
  }
 }]
}   

REST API use cases

Developers regularly use REST APIs in various scenarios due to their scalability, performance, and flexibility. Some everyday use cases include:

  • Web applications: They are commonly used for creating and managing web applications, where they handle requests and responses between the client (like a web browser) and the server.
  • Mobile applications: REST APIs are essential in mobile app development, facilitating data exchange between the app and a server. They help fetch data, send user input data to the server, and more.
  • Cloud services: Many providers offer REST APIs to interact with their services, enabling users to access resources like storage, databases, and compute instances programmatically.
  • Social media integration: Platforms like Twitter and Facebook provide REST APIs for integrating social media services into other applications.
  • IoT devices: In IoT ecosystems, REST APIs enable devices to communicate with central servers or other devices, often using lightweight data formats like JSON.

REST API principles

At a high level, REST utilizes six architectural constraints that must be met for an interface to be referred to as a true REST API. They serve as the guiding principles of REST:

  • Client–server model: The client and server apps are independent of one another and can evolve separately without any inter-dependency. This makes REST APIs more flexible and scalable.
  • Uniform interface: Resources should behave consistently across the entire API, have a single identifier to represent them, and include all of the data necessary to represent it fully while excluding unnecessary data. It also should follow clear naming conventions and link and data formats. 
  • Stateless communication: The server should treat every request as new and never store anything about the most recent HTTP request. This means no session and no history.
  • Cacheable: Caching is a strategy to improve client-side performance and reduce server load. REST APIs must state whether data is cacheable or not.
  • Layered system: APIs, stored data, and authentication requests must be spread across different interfaces. This architecture helps enhance an application’s security by limiting components in each layer to interact only with the next immediate layer. 
  • Code on demand: This is an optional constraint used the least. It permits a client to download code from the API to be executed.

REST API advantages

REST APIs provide several benefits, particularly in web and network-based application development:

  • Scalability: REST APIs can manage many requests and scale effectively due to their stateless nature.
  • Flexibility and portability: The separation of client and server and a uniform interface allow for greater flexibility and portability of applications.
  • Efficient data exchange: REST APIs can use lightweight data formats like JSON, which makes data exchange efficient.
  • Ease of development and integration: Using standard HTTP methods and a stateless protocol simplifies development and integration with other services.

REST API disadvantages

Despite their advantages, REST APIs have certain limitations:

  • Statelessness constraints: For applications requiring a continuous state or session, the stateless nature of REST can be a limitation.
  • Security considerations: As with any API exposed over the internet, REST APIs require robust security mechanisms to prevent unauthorized access and data breaches.
  • Performance overheads: In some cases, the REST architecture can introduce performance overheads, especially when dealing with large amounts of resource representations.
  • Dependency on HTTP methods: REST APIs’ reliance on standard HTTP methods may limit their use in scenarios that require more complex operations beyond basic CRUD functionalities.
  • Data over-fetching and under-fetching: Without proper design, REST APIs can lead to issues like over-fetching or under-fetching of data, where either too much or too little data is returned in a response.

REST API components

REST API components are the essential elements of a RESTful web service. These components work together to facilitate client-server communication using the principles of REST. 

Here are the critical components of a REST API: 

Resources

Resources are the fundamental component of a REST API, and specific resources that match the client’s requested location should be returned. Any piece of data can be a resource, including documents, text files, images, services, collections of other resources, and more. The state of the resource at any particular time is known as resource representation, and this consists of data, metadata describing payload, and links that can help clients get additional related data.

Unless explicitly documented otherwise, REST APIs return UTF-8 encoded JSON objects as the resource. This is designed to be easy for humans and machines to create and consume.
For example, The Nylas Platform provides most data in this format; here is an example of what it looks like for a resource that represents a user contact via the Nylas Contacts API:

{
   "request_id": "1",
   "data": [
       {
           "emails": [
               {
                   "email": "nylas@nylas.com",
                   "type": "work"
               }
           ],
           "given_name": "Sam",
           "grant_id": "2",
           "groups": [
               {
                   "id": "myContacts"
               }
           ],
           "id": "1",
           "im_addresses": [],
           "object": "contact",
           "phone_numbers": [],
           "physical_addresses": [],
           "picture_url": "",
           "surname": "DevRel",
           "source": "address_book",
           "web_pages": []
       }
   ],
   "next_cursor": "123"
}

Methods

REST uses a set of standard HTTP methods, which are actions performed on resources. The most common methods are:

  • GET: Read a resource from a server. When a client performs a GET request, the server looks for the requested data and sends it back to the client if possible. This is the default request method.
  • POST: Create a new resource on a server. When a client performs a POST request, the server creates a new entry in the database and informs the client whether the creation was successful. 
  • PUT and PATCH: Update an existing resource on a server. When a client performs a PUT or PATCH request, the server updates an entry in the database and informs the client whether the update was successful.
  • DELETE: Delete a resource from a server. When a client performs a DELETE request, the server deletes an entry in the database and informs the client whether the deletion was successful.

Representations

When a client requests a resource, the server sends the resource’s current state in understandable formats – usually JSON or XML. The client then manipulates this representation of the resource’s state as needed.

Stateless interactions

Each request from the client to the server must contain all the information necessary to understand and process the request. The server does not store session information about the client; each interaction is independent.

Endpoints 

REST APIs use Uniform Resource Identifiers (URIs) to create addresses for resources. The endpoint (or route) is the URI requested; for REST APIs, this is typically a URL, much like you would use in the web browser. For example, here is the URL for an endpoint on the Open Notify API that provides information about contacts from your email account:

curl --location 'https://api.us.nylas.com/v3/grants/<GRANT_ID>/contacts’

Endpoints can also accept query parameters that modify the request to support additional functionality. Add a question mark to the end of the resource URL followed by a list of key-value pairs to include query parameters. If you want to include multiple query parameters, separate them with an ampersand. The next endpoint example accepts query parameters limiting the total contacts retrieved:

curl --location 'https://api.us.nylas.com/v3/grants/<GRANT_ID>/contacts?limit=10

Headers and response codes

HTTP headers in REST API requests and responses hold important metadata like content type, authentication tokens, and cache controls. HTTP response codes indicate the outcome of the request, such as success (200 OK), client error (404 Not Found), or server error (500 Internal Server Error).
Headers contain all the metadata associated with the request, including information about the request and response body, authorization, caching information, and related cookies. There are numerous possible headers; here are some of the more common headers you’ll encounter while working with REST APs:

  • Content type: This indicates the media type in the response body and is used to inform the client how to process it.
  • Authorization: This is included in the request and contains the credentials used to access a specific resource. Authorization methods will be covered in more detail later.
  • WWW authenticate: The server includes this in the response header when the client attempts to access a resource that requires authorization. This is often accompanied by a 401 unauthorized error, which is covered in detail later in this article.
  • Cache-control: This allows the client and server to define caching policies, which helps reduce latency and network traffic. However, the client can only set the caching policies to whatever the server supports, so this field is important for requests and responses.

Query parameters

Used in GET requests to filter and sort resources. They are part of the URI and provide additional information for the server to process the request.

Payload 

In methods like POST and PUT, the payload contains the data sent to the server to create or update a resource. A REST payload can contain virtually any media type, but the most commonly used media type is application/json.

Payload example

Here is what a resource that represents a contact in a user’s email that’s connected to the Nylas Contact API might look like:

Node.js

Ruby

Python

Java

Curl

Response

import 'dotenv/config'
import Nylas from 'nylas'

const NylasConfig = {
 apiKey: process.env.NYLAS_API_KEY,
 apiUri: process.env.NYLAS_API_URI,
}

const nylas = new Nylas(NylasConfig)

async function createContact() {
  try {
    const contact = await nylas.contacts.create({
      identifier: process.env.GRANT_ID,
      requestBody: {
        givenName: "My",
        middleName: "Nylas",
        surname: "Friend",
        notes: "Make sure to keep in touch!",
        emails: [{type: 'work', email: 'swag@example.com'}],
        phoneNumbers: [{type: 'work', number: '(555) 555-5555'}],
        webPages: [{type: 'other', url: 'nylas.com'}]
      }
    })

    console.log('Contact:', JSON.stringify(contact))
  } catch (error) {
    console.error('Error to create contact:', error)
  }
}

createContact()
require 'nylas'	

nylas = Nylas::Client.new(api_key: "NYLAS_API_KEY")

request_body = {
  given_name: "My",
  middle_name: "Nylas",
  surname: "Friend",  
  emails: [{email: "nylas-friend@example.com", type: "work"}],
  notes: "Make sure to keep in touch!",
  phone_numbers: [{number: "555 555-5555", type: "business"}],
  web_pages: [{url: "https://www.nylas.com", type: "homepage"}]
}

contact, _ = nylas.contacts.create(identifier: "<NYLAS_GRANT_ID>", request_body: request_body)

puts contact
from dotenv import load_dotenv
load_dotenv()

import os
import sys
from nylas import Client

nylas = Client(
    os.environ.get('NYLAS_API_KEY'),
    os.environ.get('NYLAS_API_URI')
)

grant_id = os.environ.get("GRANT_ID")

contact = nylas.contacts.create(
  grant_id,
  request_body={
    "middleName": "Nylas",
    "surname": "Friend",
    "notes": "Make sure to keep in touch!",
    "emails": [{"type": "work", "email": "swag@example.com"}],
    "phoneNumbers": [{"type": "work", "number": "(555) 555-5555"}],
    "webPages": [{"type": "other", "url": "nylas.com"}]
  }
)

print(contact)
import com.nylas.NylasClient
import com.nylas.models.ContactEmail
import com.nylas.models.ContactType
import com.nylas.models.CreateContactRequest
import com.nylas.models.WebPage

fun main(args: Array<String>) {
  val nylas: NylasClient = NylasClient(apiKey = "<NYLAS_API_KEY>")
  val emails : List<ContactEmail> = listOf(ContactEmail("swag@nylas.com", ContactType.WORK))
  val webpage : List<WebPage> = listOf(WebPage("https://www.nylas.com", ContactType.WORK))

  val contactRequest = CreateContactRequest.Builder().
      emails(emails).
      companyName("Nylas").
      givenName("Nylas' Swag").
      notes("This is good swag").
      webPages(webpage).
      build()

  val contact = nylas.contacts().create("<NYLAS_GRANT_ID>", contactRequest)

  print(contact.data)
}
curl --request POST \
  --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/contacts \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY_OR_ACCESS_TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
  "birthday": "1960-12-31",
  "company_name": "Nylas",
  "emails": [
    {
      "email": "john-work@example.com",
      "type": "work"
    },
    {
      "email": "john-home@example.com",
      "type": "home"
    }
  ],
  "given_name": "John",
  "groups": [
    {
      "id": "starred"
    },
    {
      "id": "all"
    }
  ],
  "im_addresses": [
    {
      "type": "jabber",
      "im_address": "myjabberaddress"
    },
    {
      "type": "msn",
      "im_address": "mymsnaddress"
    }
  ],
  "job_title": "Software Engineer",
  "manager_name": "Bill",
  "middle_name": "Jacob",
  "nickname": "JD",
  "notes": "Loves Ramen",
  "office_location": "123 Main Street",
  "phone_numbers": [
    {
      "number": "+1-555-555-5555",
      "type": "work"
    },
    {
      "number": "+1-555-555-5556",
      "type": "home"
    }
  ],
  "physical_addresses": [
    {
      "type": "work",
      "street_address": "123 Main Street",
      "postal_code": 94107,
      "state": "CA",
      "country": "USA",
      "city": "San Francisco"
    },
    {
      "type": "home",
      "street_address": "456 Main Street",
      "postal_code": 94107,
      "state": "CA",
      "country": "USA",
      "city": "San Francisco"
    }
  ],
  "suffix": "Jr.",
  "surname": "Doe",
  "web_pages": [
    {
      "type": "work",
      "url": "http://www.linkedin.com/in/johndoe"
    },
    {
      "type": "home",
      "url": "http://www.johndoe.com"
    }
  ]
}'

How to use a REST API

Using a REST API involves several steps, from understanding the API documentation to making requests and handling responses. Below is a guide on how to effectively use a REST API:

Step 1 – Understand the API documentation

Before starting, familiarize yourself with the API’s documentation. This should include the available endpoints, request methods, expected request formats, headers, authentication requirements, and possible response formats and codes.

Step 2 – Set up the environment

Ensure that you have the necessary tools and environment for making HTTP requests. This can include software like Postman, cURL, or programming libraries specific to your chosen language (like requests in Python, HttpClient in .NET, or Axios in JavaScript).

Step 3 – Authentication

Authentication is a critical component of internet security, and any REST API that lets clients access or modify sensitive or critical data must have an authentication system in place. Common methods include API keys, OAuth tokens, or Basic Auth. 

  • With basic authentication, access is typically binary, i.e., you can access all account data and functionality or none of it, and access can typically only be revoked by changing the user’s password.
  • With OAuth, access tokens often represent both an authorized account and a set of scopes that provide access only to specified data and functionality. This makes granting and revoking access to the resources a REST client needs much easier.
  • API key authentication is a simple and widely used method for authenticating and authorizing requests to a REST API. It involves using a unique identifier, an API key, to validate the client’s identity when making the request. 

Step 4 – Make a request 

Construct and send a request to the API. This involves choosing the correct HTTP method (GET, POST, PUT, DELETE, etc.), specifying the endpoint URL, and including any necessary headers, query parameters, or body data.

REST API request example

Here is a simple yet nifty API that has information about your email contacts:

Node.js

Ruby

Python

Java

Curl

Response

import 'dotenv/config'
import Nylas from 'nylas'

const NylasConfig = {
  apiKey: process.env.NYLAS_API_KEY,
  apiUri: process.env.NYLAS_API_URI,
}

const nylas = new Nylas(NylasConfig)

async function fetchContacts() {
  try {
    const identifier = process.env.GRANT_ID
    const contacts = await nylas.contacts.list({
      identifier,
      queryParams: {}, 
    })

    console.log('Recent Contacts:', contacts)
  } catch (error) {
    console.error('Error fetching drafts:', error)
  }
}

fetchContacts()
require 'nylas'	

nylas = Nylas::Client.new(api_key: "NYLAS_API_KEY")
contacts, _ = nylas.contacts.list(identifier: ENV["NYLAS_GRANT_ID"])

contacts.each {|contact|
  puts "Name: #{contact[:given_name]} #{contact[:surname]} | " \
      "Email: #{contact[:emails][0][:email]} | ID: #{contact[:id]}"
}
from dotenv import load_dotenv
load_dotenv()

import os
import sys
from nylas import Client

nylas = Client(
    os.environ.get('NYLAS_API_KEY'),
    os.environ.get('NYLAS_API_URI')
)

grant_id = os.environ.get("GRANT_ID")
contact_id = os.environ.get("CONTACT_ID")

contacts = nylas.contacts.list(
  grant_id,
)

print(contacts)
import com.nylas.NylasClient;
import com.nylas.models.*;

public class ReadAllContacts {
  public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
    NylasClient nylas = new NylasClient.Builder("NYLAS_API_KEY").build();
    ListResponse<Contact> contacts = nylas.contacts().list("<NYLAS_GRANT_ID>");

    for(Contact contact : contacts.getData()) {
      System.out.println(contact);
      System.out.println("\n");
    }
  }
}
curl --request GET \
  --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/contacts \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY_OR_ACCESS_TOKEN>' \
  --header 'Content-Type: application/json
{
   "request_id": "1",
   "data": [
       {
           "emails": [
               {
                   "email": "nylas@nylas.com",
                   "type": "work"
               }
           ],
           "given_name": "Sam",
           "grant_id": "2",
           "groups": [
               {
                   "id": "myContacts"
               }
           ],
           "id": "1",
           "im_addresses": [],
           "object": "contact",
           "phone_numbers": [],
           "physical_addresses": [],
           "picture_url": "",
           "surname": "DevRel",
           "source": "address_book",
           "web_pages": []
       }
   ],
   "next_cursor": "123"
}

Step 5 – Handle the response: 

After making a request, the API will return a response. Based on the example from Step 4, the response will be something like: 

{
   "request_id": "1",
   "data": [
       {
           "emails": [
               {
                   "email": "nylas@nylas.com",
                   "type": "work"
               }
           ],
           "given_name": "Sam",
           "grant_id": "2",
           "groups": [
               {
                   "id": "myContacts"
               }
           ],
           "id": "1",
           "im_addresses": [],
           "object": "contact",
           "phone_numbers": [],
           "physical_addresses": [],
           "picture_url": "",
           "surname": "DevRel",
           "source": "address_book",
           "web_pages": []
       }
   ],
   "next_cursor": "123"
}

Step 6 – Process the data: 

If the request was successful, process the data returned. This could involve parsing JSON or XML and then using this data as required in your application.

Step 7 – Error handling:

Properly handle any errors. This includes understanding the status code and error message returned by the API and implementing appropriate error handling in your application.

  • The 200 status code indicates that the REST API successfully carried out the requested action and that no more action is necessary.
  • The 400 error code (bad request) is the generic client-side error status that can result from many problems, including malformed request syntax, invalid request message parameters, and incorrect request routing. When this error occurs, the client should modify the request before sending it to the REST API again.
  • The 401 error code (unauthorized) indicates that the client didn’t have sufficient privileges to operate on the requested resource. This is typically the result of inaccurate or nonexistent access credentials. The client should modify the request to include suitable authentication information.
  • The 403 error code (forbidden) indicates that the client’s request is formed correctly, but the REST API refuses to honor it. This is typically the result of the client not having the necessary permissions for the resource. This differs from a 401 error because the client is authenticated but cannot access the requested resource with the provided method.
  • The 404 error status code (not found) indicates that the REST API can’t map the client’s URI to a resource. In other words, the API can’t find the requested resource. No indication is given whether the condition is temporary or permanent, and subsequent client requests can be permissible because the resource might become available. This status code is commonly used when the server does not want to reveal why the request has been refused or when no other response is applicable.
  • The 405 error code (not allowed) indicates that the client tried to use an HTTP method that the resource does not allow. For instance, a read-only resource might only support GET, so requests to PUT, POST, or DELETE would return this error. If you encounter this error, modify your request to a method the resource allows.
  • The 429 error occurs when a client attempts too many requests within a certain timeframe. This error is triggered based on the REST API service provider’s rate limit settings, which is used to prevent their servers from overloading. To avoid this issue, you should make yourself aware of any rate limit issues the API might have and find ways to optimize queries to reduce the requests you need to make.
  • Most REST APIs use 500 status codes whenever the request handler raises an exception. This represents a problem with the REST API server; simply retrying the request may resolve this problem. If the problem persists, you should contact the REST API provider to further diagnose the issue.

Step 8 – Testing the API

This includes testing for different scenarios, handling unexpected responses, and ensuring your application behaves correctly if the API is unavailable or returns an error. You can quickly test how your REST API functions from the command line using cURL. cURL is a lightweight tool for making HTTP requests without a web browser. With it, you can make GET, POST, PUT, PATCH, and DELETE requests to a REST API by passing the -X option followed by the desired command.

Best practices to build a secure REST API integration

Security is integral to any development project, especially for REST APIs. Here is a checklist of best practices that will help you build a secure REST API integration:

  • Keep it simple: Keep your requests simple and efficient. Every time you make the solution unnecessarily complex, you create potential vulnerabilities.
  • Use HTTPS wherever possible: HTTPS is easy to use and offers many important security benefits. Specifically, you should never send access credentials or sensitive data over an unsecured HTTP connection.
  • Hash credentials when storing them: Passwords and OAuth credentials must always be hashed to protect them from exposure, particularly in the event of unauthorized access to your systems. If you need to store access credentials for future use, use a hashing algorithm like PBKDF2, bcrypt, and scrypt for increased security.
  • Never expose sensitive information in a URL: Usernames, passwords, session tokens, and API keys should not appear in the URL because this makes it possible to capture them in web server logs and, thus, easier for a malicious actor to exploit them.
  • Use OAuth: Basic authentication is fine for testing a REST API, but you should always use OAuth whenever available because it provides better control over access to data and functionality in a REST API.