Datastore Api not functioning

Hello,
I am attempting to project my already existing datastore onto a leaderboard, but I keep getting this error.

10:50:38.643 DataStore API services are not enabled! Leaderboard will not function. - Server - TimePlayedClass:57

The datastore API is on, and I am frankly stuck here. If anyone wants a certain code snippet I will provide that. But here is the leaderboard script.

--[[
  TimePlayedClass, Modified for XP @2025
  Displays top 10 players by XP from the OrderedDataStore.
  This script's responsibility is to DISPLAY data, not to save it.
]]

local PlayersService = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local RunService = game:GetService("RunService")
local ServerStorage = game:GetService("ServerStorage")

-- Assuming your main DataStoreModule saves XP to the OrderedDataStore this script reads from.
local Config = require(script.Parent.Settings)

local TimePlayedClass = {}
TimePlayedClass.__index = TimePlayedClass

-- CONSTRUCTOR
function TimePlayedClass.new()
	local new = {}
	setmetatable(new, TimePlayedClass)

	-- Load config settings
	new._dataStoreName = Config.DATA_STORE
	new._dataStoreStatName = Config.NAME_OF_STAT -- This is the key for the OrderedDataStore
	new._boardUpdateDelay = Config.LEADERBOARD_UPDATE * 60

	-- Unused properties from the original script have been removed for clarity
	-- new._useLeaderstats, new._nameLeaderstats, etc.

	new._show1stPlaceAvatar = Config.SHOW_1ST_PLACE_AVATAR
	if new._show1stPlaceAvatar == nil then new._show1stPlaceAvatar = true end
	new._doDebug = Config.DO_DEBUG

	-- This should be an OrderedDataStore for leaderboards
	new._orderedDataStore = DataStoreService:GetOrderedDataStore(new._dataStoreName)

	new._scoreBlock = script.Parent.ScoreBlock
	new._updateBoardTimer = script.Parent.UpdateBoardTimer.Timer.TextLabel

	new._apiServicesEnabled = false
	new._isMainScript = nil -- This logic should be reviewed or simplified

	-- Caches for player info to reduce API calls
	new._usernameCache = {}
	new._thumbnailCache = {}

	return new
end

-- INITIALIZATION
function TimePlayedClass:_init()
	local success, message = pcall(function()
		self._apiServicesEnabled = DataStoreService:IsApiAccessEnabled()
	end)
	if not success or not self._apiServicesEnabled then
		warn("DataStore API services are not enabled! Leaderboard will not function.")
		return
	end

	-- Initial board update
	self:_updateBoard()

	-- Start the board update loop
	coroutine.wrap(function()
		while wait(1) do
			for i = self._boardUpdateDelay, 1, -1 do
				self._updateBoardTimer.Text = "Updating in: " .. i
				wait(1)
			end
			self:_updateBoard()
		end
	end)()
end

-- Clears all entries from the board UI
function TimePlayedClass:_clearBoard()
	for _, v in pairs(script.Parent.Main.Scores:GetChildren()) do
		if v:IsA("Frame") then
			v:Destroy()
		end
	end
end

-- Formats the raw XP value for display
function TimePlayedClass:_formatScore(value)
	-- Using commas for large numbers improves readability
	local formatted = tostring(value)
	local k = 1
	while true do  
		formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
		if (k==0) then
			break
		end
	end
	return formatted
end

-- Fetches top players from the OrderedDataStore and updates the UI
function TimePlayedClass:_updateBoard()
	if self._doDebug then print("Attempting to update leaderboard...") end

	local success, pages = pcall(function()
		-- Get the top 10 players, descending order
		return self._orderedDataStore:GetSortedAsync(false, 10)
	end)

	if not success then
		warn("Failed to get data from OrderedDataStore:", pages)
		return
	end

	self:_clearBoard()

	local data = pages:GetCurrentPage()
	if #data == 0 and self._doDebug then
		print("Leaderboard is empty.")
	end

	for rank, v in ipairs(data) do
		local userId = tonumber(string.gsub(v.key, self._dataStoreStatName, ""))
		local xp = v.value
		local username = self:_getUsernameAsync(userId)

		if username then
			local newScoreBlock = self._scoreBlock:Clone()
			newScoreBlock.Player.Text = username
			newScoreBlock.Rank.Text = "#" .. rank
			newScoreBlock.Score.Text = self:_formatScore(xp) -- Use new formatter
			newScoreBlock.Name = userId
			newScoreBlock.Parent = script.Parent.Main.Scores

			-- Handle 1st place avatar
			if rank == 1 and self._show1stPlaceAvatar then
				local thumbnail = self:_getThumbnailAsync(userId)
				if thumbnail then
					script.Parent.FirstPlace.Avatar.Image = thumbnail
					script.Parent.FirstPlace.PlayerName.Text = username
				end
			end
		end
	end
	if self._doDebug then print("Leaderboard updated successfully.") end
end

-- Helper functions for getting user data with caching
function TimePlayedClass:_getUsernameAsync(userId)
	if self._usernameCache[userId] then
		return self._usernameCache[userId]
	end

	local success, result = pcall(function()
		return PlayersService:GetNameFromUserIdAsync(userId)
	end)

	if success then
		self._usernameCache[userId] = result
		return result
	else
		warn("Could not get username for UserId:", userId, "| Error:", result)
		return nil
	end
end

function TimePlayedClass:_getThumbnailAsync(userId)
	if self._thumbnailCache[userId] then
		return self._thumbnailCache[userId]
	end

	local success, result = pcall(function()
		return PlayersService:GetUserThumbnailAsync(userId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)
	end)

	if success then
		self._thumbnailCache[userId] = result
		return result
	else
		warn("Could not get thumbnail for UserId:", userId, "| Error:", result)
		return nil
	end
end


-- Main execution
local Leaderboard = TimePlayedClass.new()
Leaderboard:_init()

Are you sure API services are enabled in game settings? If so then you can try removing the return in line 58 and see if any error is displayed.

1 Like

Api services is enabled in game settings.

Did you tried removing line 58 and see what happens?

IsApiAccessEnabled this functions dont exist.

if you want to check if the API is enabled do a basic :GetAsync inside a pcall and if its not enabled you will get the error message