Skip to main content
First, check if there’s an existing Basic SDK for your technology stack and use it instead for a better dev experience!

Summary

There are two main steps to integrating Basic into your app: implement Basic Auth, then call the database APIs with the user’s access token.

Auth APIs guide

Implement signup / login flows for your app’s users

Database APIs guide

Write and display data safely in your app

Basic Auth APIs guide

Basic uses OAuth 2.0 for authentication. For more details, read about Basic Auth. In this guide, you will:
  1. Use “redirect to sign in” endpoint to redirect users to account creation / login flow
  2. Extract code from URL
  3. Use “get auth token” endpoint with extracted code
  4. Store auth token object for future API calls
1

Use "redirect to sign in" endpoint

Create a button that redirects the user to the Basic Auth page, with the following required parameters (more info on required parameters):
  • client_id='YOUR_CLIENT_ID'
  • redirect_uri='YOUR_REDIRECT_URI'
  • response_type=code
  • scope=profile
  • state='YOUR_STATE'
Redirect URL template: https://api.basic.tech/auth/authorize?response_type=code&redirect_uri=YOUR_REDIRECT_URI&scope=profile&state=YOUR_STATE&client_id=YOUR_CLIENT_ID
Replace YOUR_CLIENT_ID, YOUR_REDIRECT_URI, and YOUR_STATE with your own values. scope must be a space-separated list (for example profile alone, or profile plus datastore scopes your app needs). The live contract matches the OpenAPI spec (GET /auth/authorize).
PKCE (recommended): You may include code_challenge and code_challenge_method=S256 on the authorize request and the matching code_verifier when exchanging the code at /auth/token. See Basic Auth for the full OAuth flow.
curl --request GET \
    --url 'https://api.basic.tech/auth/authorize?response_type=code&redirect_uri='YOUR_REDIRECT_URI'&scope=profile&state='YOUR_STATE'&client_id='YOUR_CLIENT_ID''
import requests

url = "https://api.basic.tech/auth/authorize"

querystring = {"response_type":"code","client_id":"YOUR_CLIENT_ID","redirect_uri":"YOUR_REDIRECT_URI","scope":"profile","state":"YOUR_STATE"}

response = requests.request("GET", url, params=querystring)

print(response.text)
const options = {method: 'GET'};

fetch('https://api.basic.tech/auth/authorize?response_type=code&client_id='YOUR_CLIENT_ID'&redirect_uri='YOUR_REDIRECT_URI'&scope=profile&state='YOUR_STATE'', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => "https://api.basic.tech/auth/authorize?response_type=code&client_id='YOUR_CLIENT_ID'&redirect_uri='YOUR_REDIRECT_URI'&scope=profile&state='YOUR_STATE'",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET",
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #:" . $err;
} else {
    echo $response;
}
package main

import (
    "fmt"
    "net/http"
    "io/ioutil"
)

func main() {

    url := "https://api.basic.tech/auth/authorize?response_type=code&client_id='YOUR_CLIENT_ID'&redirect_uri='YOUR_REDIRECT_URI'&scope=profile&state='YOUR_STATE'"

    req, _ := http.NewRequest("GET", url, nil)

    res, _ := http.DefaultClient.Do(req)

    defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)

    fmt.Println(res)
    fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.get("https://api.basic.tech/auth/authorize?response_type=code&client_id='YOUR_CLIENT_ID'&redirect_uri='YOUR_REDIRECT_URI'&scope=profile&state='YOUR_STATE'")
.asString();
2

Extract code from URL

The authorization code will be in the URL as a code query parameter. For example: https://your-app.com/callback?code=1234567890.You need to extract the code from the URL and use it in the next step.
# Assuming the URL is stored in a variable
URL="https://your-app.com/callback?code=1234567890"
CODE=$(echo $URL | grep -o 'code=[^&]*' | cut -d'=' -f2)
echo $CODE
from urllib.parse import urlparse, parse_qs

# Example URL
url = "https://your-app.com/callback?code=1234567890"

# Parse the URL and extract the code parameter
parsed_url = urlparse(url)
code = parse_qs(parsed_url.query)['code'][0]

print(code)
// Example URL
const url = "https://your-app.com/callback?code=1234567890";

// Extract the code parameter
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');

console.log(code);
<?php
// Example URL
$url = "https://your-app.com/callback?code=1234567890";

// Parse the URL and extract the code parameter
$query = parse_url($url, PHP_URL_QUERY);
parse_str($query, $params);
$code = $params['code'];

echo $code;
?>
package main

import (
    "fmt"
    "net/url"
)

func main() {
    // Example URL
    rawURL := "https://your-app.com/callback?code=1234567890"
    
    // Parse the URL and extract the code parameter
    parsedURL, _ := url.Parse(rawURL)
    code := parsedURL.Query().Get("code")
    
    fmt.Println(code)
}
import java.net.URI;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        // Example URL
        String url = "https://your-app.com/callback?code=1234567890";
        
        // Parse the URL and extract the code parameter
        String query = URI.create(url).getQuery();
        Map<String, String> params = new HashMap<>();
        for (String param : query.split("&")) {
            String[] pair = param.split("=");
            params.put(pair[0], URLDecoder.decode(pair[1], StandardCharsets.UTF_8));
        }
        String code = params.get("code");
        
        System.out.println(code);
    }
}
3

Use "get auth token" endpoint with extracted code

Make a post request to /auth/token with the authorization code in the body. The response will be a JSON object with the access token and a refresh code.Token URL template: https://api.basic.tech/auth/token
Make sure to replace YOUR_CODE with your own values
curl --request POST \
    --url 'https://api.basic.tech/auth/token' \
    --header 'Content-Type: application/json' \
    --data '{"code":"YOUR_CODE"}'
import requests

url = "https://api.basic.tech/auth/token"

payload = {"code": "YOUR_CODE"}
headers = {"Content-Type": "application/json"}

response = requests.request("POST", url, json=payload, headers=headers)

print(response.text)
const options = {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({code: 'YOUR_CODE'})
};

fetch('https://api.basic.tech/auth/token', options)
.then(response => response.json())
.then(response => console.log(response))
<?php

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => "https://api.basic.tech/auth/token",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => "{\n  \"code\": \"YOUR_CODE\"\n}",
    CURLOPT_HTTPHEADER => [
        "Content-Type: application/json"
    ],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
    "fmt"
    "strings"
    "net/http"
    "io/ioutil"
)

func main() {

    url := "https://api.basic.tech/auth/token"

    payload := strings.NewReader("{\n  \"code\": \"YOUR_CODE\"\n}")

    req, _ := http.NewRequest("POST", url, payload)

    req.Header.Add("Content-Type", "application/json")

    res, _ := http.DefaultClient.Do(req)

    defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)

    fmt.Println(res)
    fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://api.basic.tech/auth/token")
.header("Content-Type", "application/json")
.body("{\n  \"code\": \"YOUR_CODE\"\n}")
.asString();
4

Store auth token object for future API calls

The response from the token endpoint will look like this:
{
  "access_token": "<string>",
  "token_type": "<string>",
  "expires_in": 123,
  "refresh_token": "<string>"
}

Basic database APIs guide

The database APIs are easy to use. Make sure to check the validity of the access_token, and pass it in the Header of your API call. If the access_token is expired, you’d repeat step 3 of the Auth APIs guide but using the refresh_token instead of the extracted code. This will return you a fresh new access_token. Here’s how to validate and use the access token in different programming languages:
# Note: For bash, you'll need to use a JWT decoding tool like jq or jwt-cli
# Example using jwt-cli:
# if jwt decode YOUR_ACCESS_TOKEN | jq '.exp > now' | grep -q "true"; then
#   # Token is valid, proceed with API calls
curl --request GET \
 --url 'https://api.basic.tech/your-endpoint' \
 --header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
# else
#   # Token is expired, refresh it
curl --request POST \
 --url 'https://api.basic.tech/auth/token' \
 --header 'Content-Type: application/json' \
 --data '{"refresh_token":"YOUR_REFRESH_TOKEN"}'
import jwt
import time
import requests

def refresh_token(refresh_token):
    response = requests.post(
        'https://api.basic.tech/auth/token',
        json={'refresh_token': refresh_token},
        headers={'Content-Type': 'application/json'}
    )
    return response.json()

def is_token_valid(access_token):
    try:
        # Decode the token without verification
        decoded = jwt.decode(access_token, options={"verify_signature": False})
        # Check if token is expired
        return decoded['exp'] > time.time()
    except:
        return False

# Example usage
if is_token_valid(access_token):
    # Token is valid, proceed with API calls
    headers = {'Authorization': f'Bearer {access_token}'}
    response = requests.get('https://api.basic.tech/your-endpoint', headers=headers)
else:
    # Token is invalid, refresh it
    new_tokens = refresh_token(refresh_token)
    access_token = new_tokens['access_token']
    refresh_token = new_tokens['refresh_token']
    
    # Now use the new access token
    headers = {'Authorization': f'Bearer {access_token}'}
    response = requests.get('https://api.basic.tech/your-endpoint', headers=headers)
import jwtDecode from 'jwt-decode';

async function refreshToken(refreshToken) {
    const response = await fetch('https://api.basic.tech/auth/token', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({ refresh_token: refreshToken })
    });
    return await response.json();
}

function isTokenValid(accessToken) {
    try {
        const decoded = jwtDecode(accessToken);
        // Check if token is expired
        return decoded.exp * 1000 > Date.now();
    } catch (error) {
        return false;
    }
}

// Example usage
if (isTokenValid(accessToken)) {
    // Token is valid, proceed with API calls
    const response = await fetch('https://api.basic.tech/your-endpoint', {
        headers: {
            'Authorization': `Bearer ${accessToken}`
        }
    });
} else {
    // Token is invalid, refresh it
    const newTokens = await refreshToken(refreshToken);
    accessToken = newTokens.access_token;
    refreshToken = newTokens.refresh_token;
    
    // Now use the new access token
    const response = await fetch('https://api.basic.tech/your-endpoint', {
        headers: {
            'Authorization': `Bearer ${accessToken}`
        }
    });
}
<?php
use Firebase\JWT\JWT;

function refreshToken($refreshToken) {
    $ch = curl_init('https://api.basic.tech/auth/token');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json'
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
        'refresh_token' => $refreshToken
    ]));
    
    $response = curl_exec($ch);
    curl_close($ch);
    
    return json_decode($response, true);
}

function isTokenValid($accessToken) {
    try {
        $decoded = JWT::decode($accessToken, null, false);
        return $decoded->exp > time();
    } catch (Exception $e) {
        return false;
    }
}

// Example usage
if (isTokenValid($accessToken)) {
    // Token is valid, proceed with API calls
    $ch = curl_init('https://api.basic.tech/your-endpoint');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Bearer ' . $accessToken
    ]);
    $response = curl_exec($ch);
    curl_close($ch);
} else {
    // Token is invalid, refresh it
    $newTokens = refreshToken($refreshToken);
    $accessToken = $newTokens['access_token'];
    $refreshToken = $newTokens['refresh_token'];
    
    // Now use the new access token
    $ch = curl_init('https://api.basic.tech/your-endpoint');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Bearer ' . $accessToken
    ]);
    $response = curl_exec($ch);
    curl_close($ch);
}
?>
package main

import (
    "fmt"
    "time"
    "net/http"
    "io/ioutil"
    "encoding/json"
    "github.com/golang-jwt/jwt/v5"
)

type TokenResponse struct {
    AccessToken  string `json:"access_token"`
    RefreshToken string `json:"refresh_token"`
}

func refreshToken(refreshToken string) (*TokenResponse, error) {
    payload := map[string]string{
        "refresh_token": refreshToken,
    }
    jsonData, _ := json.Marshal(payload)

    req, _ := http.NewRequest("POST", "https://api.basic.tech/auth/token", bytes.NewBuffer(jsonData))
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    var tokenResp TokenResponse
    err = json.NewDecoder(resp.Body).Decode(&tokenResp)
    return &tokenResp, err
}

func isTokenValid(accessToken string) bool {
    token, _, err := jwt.NewParser().ParseUnverified(accessToken, jwt.MapClaims{})
    if err != nil {
        return false
    }

    if claims, ok := token.Claims.(jwt.MapClaims); ok {
        exp := claims["exp"].(float64)
        return int64(exp) > time.Now().Unix()
    }
    return false
}

func main() {
    if isTokenValid(accessToken) {
        // Token is valid, proceed with API calls
        req, _ := http.NewRequest("GET", "https://api.basic.tech/your-endpoint", nil)
        req.Header.Add("Authorization", "Bearer "+accessToken)

        client := &http.Client{}
        resp, _ := client.Do(req)
        defer resp.Body.Close()
        body, _ := ioutil.ReadAll(resp.Body)
        fmt.Println(string(body))
    } else {
        // Token is invalid, refresh it
        newTokens, err := refreshToken(refreshToken)
        if err != nil {
            fmt.Println("Error refreshing token:", err)
            return
        }
        
        accessToken = newTokens.AccessToken
        refreshToken = newTokens.RefreshToken
        
        // Now use the new access token
        req, _ := http.NewRequest("GET", "https://api.basic.tech/your-endpoint", nil)
        req.Header.Add("Authorization", "Bearer "+accessToken)

        client := &http.Client{}
        resp, _ := client.Do(req)
        defer resp.Body.Close()
        body, _ := ioutil.ReadAll(resp.Body)
        fmt.Println(string(body))
    }
}
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import java.util.Date;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import com.google.gson.Gson;

class TokenResponse {
    String access_token;
    String refresh_token;
}

public class TokenValidator {
    private static final HttpClient client = HttpClient.newHttpClient();
    private static final Gson gson = new Gson();

    public static TokenResponse refreshToken(String refreshToken) throws Exception {
        String json = String.format("{\"refresh_token\":\"%s\"}", refreshToken);
        
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.basic.tech/auth/token"))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(json))
            .build();

        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        return gson.fromJson(response.body(), TokenResponse.class);
    }

    public static boolean isTokenValid(String accessToken) {
        try {
            Claims claims = Jwts.parserBuilder()
                .build()
                .parseClaimsJwt(accessToken)
                .getBody();
            
            Date expiration = claims.getExpiration();
            return expiration.after(new Date());
        } catch (Exception e) {
            return false;
        }
    }

    public static void main(String[] args) {
        if (isTokenValid(accessToken)) {
            // Token is valid, proceed with API calls
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://api.basic.tech/your-endpoint"))
                .header("Authorization", "Bearer " + accessToken)
                .build();

            try {
                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                System.out.println(response.body());
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            // Token is invalid, refresh it
            try {
                TokenResponse newTokens = refreshToken(refreshToken);
                accessToken = newTokens.access_token;
                refreshToken = newTokens.refresh_token;
                
                // Now use the new access token
                HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://api.basic.tech/your-endpoint"))
                    .header("Authorization", "Bearer " + accessToken)
                    .build();

                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                System.out.println(response.body());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}