curl --request GET \
--url https://app.base44.com/api/apps/{app_id}/seo/last-scan \
--header 'Authorization: Bearer <token>'import requests
url = "https://app.base44.com/api/apps/{app_id}/seo/last-scan"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.base44.com/api/apps/{app_id}/seo/last-scan', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.base44.com/api/apps/{app_id}/seo/last-scan",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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"
)
func main() {
url := "https://app.base44.com/api/apps/{app_id}/seo/last-scan"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.base44.com/api/apps/{app_id}/seo/last-scan")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/seo/last-scan")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"result": {
"score": {
"overall": 82,
"grade": "B",
"categories": {
"meta_tags": {
"failures": 0,
"passed": 4,
"score": 80,
"warnings": 1
}
}
},
"scanned_at": "2026-09-03T09:15:00+00:00",
"checks": [
{
"category": "ai_discoverability",
"description": "Turn on the AI site guide so AI engines can understand your app.",
"id": "llms_txt",
"status": "warn",
"title": "AI-readable site guide is off"
}
]
}
}Get last SEO scan
Returns the app’s last SEO scan in full, its score and checklist together.
This returns the same score and checklist Run SEO scan returned when it ran, so poll this rather than re-scanning to re-read a result. Anything else that scan’s response carried isn’t persisted, so it never appears here. It returns null until the app is scanned at least once, and the result is only as current as the last scan, so read scanned_at before acting on it.
The score and the checklist are stored separately, and two scans running at once can interleave those two writes. So compare scanned_at with the one Get SEO score returns before treating the two as one scan’s.
curl --request GET \
--url https://app.base44.com/api/apps/{app_id}/seo/last-scan \
--header 'Authorization: Bearer <token>'import requests
url = "https://app.base44.com/api/apps/{app_id}/seo/last-scan"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.base44.com/api/apps/{app_id}/seo/last-scan', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.base44.com/api/apps/{app_id}/seo/last-scan",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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"
)
func main() {
url := "https://app.base44.com/api/apps/{app_id}/seo/last-scan"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.base44.com/api/apps/{app_id}/seo/last-scan")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/seo/last-scan")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"result": {
"score": {
"overall": 82,
"grade": "B",
"categories": {
"meta_tags": {
"failures": 0,
"passed": 4,
"score": 80,
"warnings": 1
}
}
},
"scanned_at": "2026-09-03T09:15:00+00:00",
"checks": [
{
"category": "ai_discoverability",
"description": "Turn on the AI site guide so AI engines can understand your app.",
"id": "llms_txt",
"status": "warn",
"title": "AI-readable site guide is off"
}
]
}
}Authorizations
Personal access token, sent as Authorization: Bearer <token>. Each operation lists the permission it needs: read_only or full_access. A full-access token can call every operation. A read-only token can call only the operations that list read_only; anything else returns 403 read_only_credential_route_not_allowed.
Path Parameters
ID of the app.
Response
The last scan, or null if the app has never been scanned.
The stored scan.
The app's most recent scan, or null if it has never been scanned.
Show child attributes
Show child attributes
Was this page helpful?