SpareSpare Docs
GuidesAPI Reference

Freelance Verification

Verify a freelancer's certificate and its status using their National ID and certificate number.

Integration guide

Goal: Confirm a freelancer's certificate is authentic and active, and retrieve the freelancer and certificate details.

Estimated time: 15 minutes

Prerequisites

  • Sandbox credentials and an access token
  • The freelancer's National ID and certificate number

When to use

  • Freelance marketplaces running background checks
  • Recruitment platforms vetting candidates
  • Any workflow that must confirm a professional credential before engagement

What it returns

Freelancer Verification has two endpoints:

EndpointMethod and URLUse it when
Certificate DetailsPOST /api/v2.0/av/FreelancerVerification/CertificateDetailsYou need the freelancer's details and the full certificate record
Certificate StatusGET /api/v2.0/av/FreelancerVerification/GetCertificateStatus?certificateNumber={certificateNumber}You only need the certificate's current status

The Certificate Details endpoint requires the freelancer's nationalId and certificateNumber. The Certificate Status endpoint only requires certificateNumber as a query parameter.

EndpointResponse
Certificate DetailsFreelancer name in English and Arabic, gender, National ID, certificate status, issue and expiry dates, certificate number, specialization, and category
Certificate StatusCurrent status, issue date, expiry date, license number, and revocation or cancellation date when applicable

Certificate status can be Active, Revoked, Rejected, Expired, Canceled, or Pending.

Integration summary

Authenticate

Obtain a Bearer access token from your API credentials.

Get certificate details

Use this endpoint when you need the full freelancer and certificate record:

POST /api/v2.0/av/FreelancerVerification/CertificateDetails

curl -X POST https://sandbox.sparefinancial.sa/api/v2.0/av/FreelancerVerification/CertificateDetails \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "nationalId": "1106972886", "certificateNumber": "FL-669844156" }'
const res = await fetch(
  "https://sandbox.sparefinancial.sa/api/v2.0/av/FreelancerVerification/CertificateDetails",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${accessToken}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      nationalId: "1106972886",
      certificateNumber: "FL-669844156",
    }),
  },
);

const data = await res.json();
import requests

res = requests.post(
    "https://sandbox.sparefinancial.sa/api/v2.0/av/FreelancerVerification/CertificateDetails",
    headers={
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json",
    },
    json={
        "nationalId": "1106972886",
        "certificateNumber": "FL-669844156",
    },
)

data = res.json()
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

HttpClient client = HttpClient.newHttpClient();

String body = """
    { "nationalId": "1106972886", "certificateNumber": "FL-669844156" }
    """;

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://sandbox.sparefinancial.sa/api/v2.0/av/FreelancerVerification/CertificateDetails"))
    .header("Authorization", "Bearer " + accessToken)
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

String result = response.body();
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

using var client = new HttpClient();

var request = new HttpRequestMessage(
    HttpMethod.Post,
    "https://sandbox.sparefinancial.sa/api/v2.0/av/FreelancerVerification/CertificateDetails");
request.Headers.Add("Authorization", $"Bearer {accessToken}");
request.Content = new StringContent(
    "{ \"nationalId\": \"1106972886\", \"certificateNumber\": \"FL-669844156\" }",
    Encoding.UTF8,
    "application/json");

var response = await client.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();
package main

import (
	"bytes"
	"io"
	"net/http"
)

payload := []byte(`{ "nationalId": "1106972886", "certificateNumber": "FL-669844156" }`)

req, err := http.NewRequest(
	http.MethodPost,
	"https://sandbox.sparefinancial.sa/api/v2.0/av/FreelancerVerification/CertificateDetails",
	bytes.NewReader(payload),
)
if err != nil {
	panic(err)
}

req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Content-Type", "application/json")

res, err := http.DefaultClient.Do(req)
if err != nil {
	panic(err)
}
defer res.Body.Close()

body, _ := io.ReadAll(res.Body)

Get the certificate status

Use this endpoint when you only need the certificate's current status:

GET /api/v2.0/av/FreelancerVerification/GetCertificateStatus?certificateNumber={certificateNumber}

curl -X GET "https://sandbox.sparefinancial.sa/api/v2.0/av/FreelancerVerification/GetCertificateStatus?certificateNumber=FL-669844156" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
const certificateNumber = "FL-669844156";
const url = new URL(
  "https://sandbox.sparefinancial.sa/api/v2.0/av/FreelancerVerification/GetCertificateStatus",
);
url.searchParams.set("certificateNumber", certificateNumber);

const res = await fetch(url, {
  headers: {
    Authorization: `Bearer ${accessToken}`,
  },
});

const data = await res.json();
import requests

res = requests.get(
    "https://sandbox.sparefinancial.sa/api/v2.0/av/FreelancerVerification/GetCertificateStatus",
    headers={
        "Authorization": f"Bearer {access_token}",
    },
    params={
        "certificateNumber": "FL-669844156",
    },
)

data = res.json()
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create(
        "https://sandbox.sparefinancial.sa/api/v2.0/av/FreelancerVerification/GetCertificateStatus?certificateNumber=FL-669844156"))
    .header("Authorization", "Bearer " + accessToken)
    .GET()
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
String body = response.body();
using System;
using System.Net.Http;
using System.Threading.Tasks;

using var client = new HttpClient();

var request = new HttpRequestMessage(
    HttpMethod.Get,
    "https://sandbox.sparefinancial.sa/api/v2.0/av/FreelancerVerification/GetCertificateStatus?certificateNumber=FL-669844156");
request.Headers.Add("Authorization", $"Bearer {accessToken}");

var response = await client.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();
package main

import (
	"io"
	"net/http"
)

req, err := http.NewRequest(
	http.MethodGet,
	"https://sandbox.sparefinancial.sa/api/v2.0/av/FreelancerVerification/GetCertificateStatus?certificateNumber=FL-669844156",
	nil,
)
if err != nil {
	panic(err)
}

req.Header.Set("Authorization", "Bearer "+accessToken)

res, err := http.DefaultClient.Do(req)
if err != nil {
	panic(err)
}
defer res.Body.Close()

body, _ := io.ReadAll(res.Body)

Use the certificate status

Treat only Active certificates as valid. A different status means the certificate should be blocked or reviewed.

Handle request errors separately: invalid input (400), expired or invalid token (401), certificate not found (404), and a National ID that does not match the certificate (412).

Sandbox testing

Use these National ID and certificate combinations to exercise the success and error paths.

Successful

National IDCertificate number
1106972886FL-669844156
1000000000FL-511414201

Error scenarios

National IDCertificate numberResult
123456FL-469744146400 National ID invalid
10000000001234400 certificate number invalid
1000000000FL-250336300404 certificate number not found
1000000000FL-566558999412 National ID does not match certificate

Key takeaways

  • Use Certificate Details when you need the freelancer and certificate record.
  • Use Certificate Status when you only need the certificate's current status.
  • Treat only Active certificates as valid. Other statuses should block the request or trigger a review.

On this page