Proud moment for Kenya as three homegrown startups storm into Africa’s MEST Challenge semi-finals

Proud moment for Kenya as three homegrown startups storm into Africa’s MEST Challenge semi-finals

Kenyan innovators are making waves across Africa after three local startups advanced to the semi-finals of the 2025 MEST Africa Challenge. (Photo: Courtesy)

Read this story aloud

Listen to the clean text version of this article

Ready
3 min listen
Audio reading is not supported on this browser.

Three Kenyan ventures—Logistify AI, Farmsky Ventures, and Investa Farm—have been named among Africa’s top 20 innovators in the prestigious MEST Africa Challenge 2025

Three Kenyan startups have advanced to the semi-finals of the 2025 MEST Africa Challenge (MAC), a continental competition that recognises innovative fintech and high-value chain solutions.
Now in its seventh edition, the competition is organised by MEST Africa in partnership with Absa.
This year’s theme, “You Build, We Scale,” invited founders from Absa’s eight priority markets—Botswana, Ghana, Kenya, Mauritius, Mozambique, Seychelles, Uganda, and Zambia—to develop scalable financial solutions.
The three Kenyan startups that made it to the semi-finals are Logistify AI, an AI-powered procurement and supply chain platform for small and medium-sized enterprises; Farmsky Ventures, a digital lending and crop insurance platform for smallholder farmers; and Investa Farm, which offers voucher-backed loans for climate-resilient farm inputs to help farmers access vital resources.
“Each of these founders represents a unique path toward reimagining how finance works for Africans,” said Ashwin Ravichandran, Portfolio Advisor at MEST Africa and MAC Lead.
“Their ideas pair technology with empathy, proving that lasting change comes from solving real problems within their own communities.”

Latest Stories

  • Cherotich, Odira shine as Kenya dominates Prefontaine Classic despite rare Kipyegon defeat
  • Kenya reaffirms ties with Rwanda as it marks Liberation Day celebrations
  • Morocco continue historic rise with record-breaking World Cup victory against Canada
  • Serena Williams withdraws from Wimbledon doubles after knee injury, ending Venus reunion plans

The Kenyan startups will compete alongside 17 other ventures from across the continent. Botswana is represented by mystock.africa, while Ghana’s entries include Brydge and Kutana Technologies Limited. Other semi-finalists include Black Swan (Mauritius), Fusepay (Seychelles), and Simulador Bancário (Mozambique).
Uganda has several representatives—Paytota, Xzerra, Kanzu Finance Limited, Axiom Zorn, Credify Africa Inc., and eMaisha Pay—while Zambia’s contenders include Ebusaka Green Technology Limited, KreativBox Technology, Mighty Finance Solution Inc., Devdraft Ai, and Homer Price Agency Solutions Limited.
Online pitches
The semi-finalists will present their pitches online during the week of October 27, 2025. The ten strongest ventures will move on to the Final Demo Day in Cape Town, South Africa, on November 26.
The overall winner will receive $50,000 (Sh6.4 million) in equity funding, gain access to MEST Africa’s extensive network of mentors and investors, and have the opportunity to pilot projects in collaboration with Absa.
“Congratulations to the top 20 finalists,” said Tawanda Chatikobo, Head of Digital for Absa Regional Operations, Retail and Business Banking.
“The quality of submissions has been exceptional, showcasing the depth of innovation and entrepreneurial drive across Africa. Our partnership with MEST reflects our commitment to open collaboration within the FinTech ecosystem.”

Other Topics To Read

Top Stories Today

  • Cherotich, Odira shine as Kenya dominates Prefontaine Classic despite rare Kipyegon defeat
  • Mbappé fires France past Paraguay into World Cup quarter-finals
  • Weekly new Ebola cases reach highest level since outbreak began: WHO
  • Kenya reaffirms ties with Rwanda as it marks Liberation Day celebrations
  • Serena Williams withdraws from Wimbledon doubles after knee injury, ending Venus reunion plans
  • Report records 83 harassment incidents against Christians in Israel over three months

`;
}

return “;
}

function commentActionsMarkup(comment, canComment) {
const likeLabel = comment.liked_by_me ? ‘Liked’ : ‘Like’;
const likeCount = Number(comment.like_count || 0) > 0
? “
: ”;

const likeButton = canComment && comment.status === ‘approved’
? “
: “;

const replyButton = canComment && comment.status === ‘approved’
? “
: ”;

return `

`;
}

function commentMarkup(comment, canComment, isReply = false) {
const pendingBadge = comment.status && comment.status !== ‘approved’
? “
: ”;

const edited = comment.is_edited
? “
: ”;

const repliesHtml = Array.isArray(comment.replies) && comment.replies.length
? `

`
: “;

return `

`;
}

function replyFormMarkup(commentId) {
return `

`;
}

function setNotice(widget, message, type = ‘info’) {
const notice = widget.querySelector(‘[data-role=”notice”]’);
if (!notice) return;

if (!message) {
notice.hidden = true;
notice.textContent = ”;
notice.classList.remove(‘is-error’);
return;
}

notice.hidden = false;
notice.textContent = message;
notice.classList.toggle(‘is-error’, type === ‘error’);
}

function setCount(widget, total) {
const count = widget.querySelector(‘[data-role=”count”]’);
if (!count) return;

const num = Number(total || 0);
count.textContent = num === 1 ? ‘1 comment’ : `${num} comments`;
}

function openReplyBox(widget, commentId) {
widget.querySelectorAll(‘[data-role=”reply-box”]’).forEach(box => {
box.hidden = true;
box.innerHTML = ”;
});

const targetItem = widget.querySelector(`.ev-comments__item[data-comment-id=”${commentId}”]`);
if (!targetItem) return;

const replyBox = targetItem.querySelector(‘[data-role=”reply-box”]’);
if (!replyBox) return;

replyBox.hidden = false;
replyBox.innerHTML = replyFormMarkup(commentId);

const textarea = replyBox.querySelector(‘textarea’);
if (textarea) textarea.focus();
}

function closeReplyBox(container) {
if (!container) return;
container.hidden = true;
container.innerHTML = ”;
}

async function initCommentsWidget(widget) {
const state = {
articleId: Number(widget.dataset.articleId),
loadUrl: widget.dataset.loadUrl,
storeUrl: widget.dataset.storeUrl,
commentsBaseUrl: widget.dataset.commentsBaseUrl,
canComment: widget.dataset.canComment === ‘1’,
page: 1,
perPage: 10,
sort: ‘newest’,
total: 0,
hasMore: false,
busy: false
};

const list = widget.querySelector(‘[data-role=”list”]’);
const loading = widget.querySelector(‘[data-role=”loading”]’);
const empty = widget.querySelector(‘[data-role=”empty”]’);
const loadMoreBtn = widget.querySelector(‘[data-role=”load-more”]’);
const sortSelect = widget.querySelector(‘[data-role=”sort”]’);
const composerForm = widget.querySelector(‘[data-role=”composer-form”]’);

async function loadComments(reset = true) {
if (state.busy) return;

state.busy = true;
setNotice(widget, ”);
loading.hidden = false;

if (reset) {
state.page = 1;
list.innerHTML = ”;
empty.hidden = true;
}

try {
const url = new URL(state.loadUrl, window.location.origin);
url.searchParams.set(‘page’, state.page);
url.searchParams.set(‘per_page’, state.perPage);
url.searchParams.set(‘sort’, state.sort);

const response = await requestJson(url.toString(), {
method: ‘GET’,
headers: {
‘Accept’: ‘application/json’,
‘X-Requested-With’: ‘XMLHttpRequest’
}
});

const items = Array.isArray(response.data) ? response.data : [];
const meta = response.meta || {};

state.total = Number(meta.total || 0);
state.hasMore = !!meta.has_more;

setCount(widget, state.total);

if (reset) {
list.innerHTML = ”;
}

if (!items.length && reset) {
empty.hidden = false;
} else {
empty.hidden = true;
list.insertAdjacentHTML(
‘beforeend’,
items.map(item => commentMarkup(item, state.canComment, false)).join(”)
);
}

loadMoreBtn.hidden = !state.hasMore;
} catch (error) {
if (!list.children.length) {
empty.hidden = false;
empty.textContent = ‘Unable to load comments right now.’;
}
setNotice(widget, error.message || ‘Unable to load comments.’, ‘error’);
} finally {
loading.hidden = true;
state.busy = false;
}
}

async function submitTopLevelComment(form) {
const textarea = form.querySelector(‘textarea[name=”content”]’);
const button = form.querySelector(‘[data-role=”submit-comment”]’);

if (!textarea) return;

const content = textarea.value.trim();
if (!content) return;

const originalText = button ? button.textContent : ”;

try {
if (button) {
button.disabled = true;
button.textContent = ‘Posting…’;
}

const response = await requestJson(state.storeUrl, {
method: ‘POST’,
headers: buildJsonHeaders(),
body: JSON.stringify({
article_id: state.articleId,
content: content,
source_url: window.location.href
})
});

textarea.value = ”;

if (response?.data) {
list.insertAdjacentHTML(
‘afterbegin’,
commentMarkup(response.data, state.canComment, false)
);
empty.hidden = true;

if ((response.data.status || ”) === ‘approved’) {
state.total += 1;
setCount(widget, state.total);
}
}

setNotice(widget, response.message || ‘Comment posted successfully.’);
} catch (error) {
setNotice(widget, error.message || ‘Unable to post comment.’, ‘error’);
} finally {
if (button) {
button.disabled = false;
button.textContent = originalText || ‘Post comment’;
}
}
}

async function submitReply(form) {
const commentId = Number(form.dataset.commentId || 0);
const textarea = form.querySelector(‘textarea[name=”content”]’);
const button = form.querySelector(‘.ev-comments__reply-submit’);

if (!commentId || !textarea) return;

const content = textarea.value.trim();
if (!content) return;

const originalText = button ? button.textContent : ”;

try {
if (button) {
button.disabled = true;
button.textContent = ‘Posting…’;
}

const response = await requestJson(`${state.commentsBaseUrl}/${commentId}/reply`, {
method: ‘POST’,
headers: buildJsonHeaders(),
body: JSON.stringify({
article_id: state.articleId,
content: content,
source_url: window.location.href
})
});

if (response?.data) {
const parentItem = widget.querySelector(`.ev-comments__item[data-comment-id=”${commentId}”]`);
if (parentItem) {
const repliesWrap = parentItem.querySelector(‘.ev-comments__replies’);
if (repliesWrap) {
repliesWrap.insertAdjacentHTML(
‘beforeend’,
commentMarkup(response.data, state.canComment, true)
);
}
}
}

closeReplyBox(form.closest(‘[data-role=”reply-box”]’));
setNotice(widget, response.message || ‘Reply posted successfully.’);
} catch (error) {
setNotice(widget, error.message || ‘Unable to post reply.’, ‘error’);
} finally {
if (button) {
button.disabled = false;
button.textContent = originalText || ‘Post reply’;
}
}
}

async function toggleLike(button) {
const commentId = Number(button.dataset.commentId || 0);
if (!commentId) return;

const originalHtml = button.innerHTML;

try {
button.disabled = true;
button.innerHTML = ‘Working…’;

const response = await requestJson(`${state.commentsBaseUrl}/${commentId}/like`, {
method: ‘POST’,
headers: buildJsonHeaders(),
body: JSON.stringify({})
});

const liked = !!response?.data?.liked;
const likeCount = Number(response?.data?.like_count || 0);

button.classList.toggle(‘is-liked’, liked);
button.innerHTML = `${liked ? ‘Liked’ : ‘Like’} ${likeCount > 0 ? “ : ”}`;
} catch (error) {
button.innerHTML = originalHtml;
setNotice(widget, error.message || ‘Unable to update like.’, ‘error’);
} finally {
button.disabled = false;
}
}

if (composerForm) {
composerForm.addEventListener(‘submit’, function (e) {
e.preventDefault();
submitTopLevelComment(composerForm);
});
}

if (sortSelect) {
sortSelect.addEventListener(‘change’, function () {
state.sort = this.value || ‘newest’;
loadComments(true);
});
}

if (loadMoreBtn) {
loadMoreBtn.addEventListener(‘click’, function () {
if (state.busy || !state.hasMore) return;
state.page += 1;
loadComments(false);
});
}

widget.addEventListener(‘click’, function (e) {
const likeBtn = e.target.closest(‘[data-action=”toggle-like”]’);
if (likeBtn) {
e.preventDefault();
toggleLike(likeBtn);
return;
}

const replyBtn = e.target.closest(‘[data-action=”toggle-reply”]’);
if (replyBtn) {
e.preventDefault();
openReplyBox(widget, Number(replyBtn.dataset.commentId || 0));
return;
}

const cancelReplyBtn = e.target.closest(‘[data-action=”cancel-reply”]’);
if (cancelReplyBtn) {
e.preventDefault();
closeReplyBox(cancelReplyBtn.closest(‘[data-role=”reply-box”]’));
}
});

widget.addEventListener(‘submit’, function (e) {
const replyForm = e.target.closest(‘.ev-comments__reply-form’);
if (replyForm) {
e.preventDefault();
submitReply(replyForm);
}
});

loadComments(true);
}

document.addEventListener(‘DOMContentLoaded’, function () {
document.querySelectorAll(‘.ev-comments’).forEach(initCommentsWidget);
});
})();

Trending


Morocco continue historic rise with record-breaking World Cup victory against CanadaSports
|Erick Kariuki
|8 hours ago

Cherotich, Odira shine as Kenya dominates Prefontaine Classic despite rare Kipyegon defeatSports
|Erick Kariuki
|33 minutes ago

Slum residents urged to adopt ‘localised solutions’ to mitigate climate change effectsNews
|Hussein Hassan
|18 hours ago

From mixing dirty whites to overloading the machine: 6 common laundry mistakesLifestyle
|Margaret Wanjiru
|20 hours ago

WHO launches clinical trial in DRC to test Ebola treatmentsDemocratic Republic of Congo
|Bashir Mbuthia
|1 day ago

Six killed as matatu, trailer collide head-on along Nakuru-Eldoret highwayNews
|Rachael Mutabasi
|23 hours ago

Colombia beats Ghana to complete World Cup round of 16 lineupSports
|XINHUA
|22 hours ago

16 CITAM Woodley pupils stable after bee attack during Lake Baringo tourNews
|Rachael Mutabasi
|20 hours ago

60 more Kenyans arrive home from South Africa as government steps up evacuationsNews
|Mary Wambui
|19 hours ago
Sudanese army intensify offensive to retake strategic city of Kurmuk on Ethiopia borderRegional
|Addis Standard
|16 hours ago

Share.
Leave A Reply

Exit mobile version