The requested URL was rejected. Please consult with your administrator. Your support ID is: 8780736962620738016

Hello. I am receiving the following response when attempting to make an HTTP request: The requested URL was rejected. Please consult with your administrator. Your support ID is: 8780736962620738016.

The error happens exactly on the line below:

let requestToPay = nk.httpRequest(requestUrl, "post", requestHeaders, JSON.stringify(requestBody));

Please refer to the rest of my code below and help:

// Define MTN MoMo API Configuration
const MOMO_API_BASE_URL = "https://proxy.momoapi.mtn.com"; // Use sandbox for testing
const MOMO_PRIMARY_KEY = "cc442xxxxxxxxxxxxxxxxx4e"; // Replace with your actual key
const MOMO_API_USER_ID = "bxxxxxxxxxxxxxxxxxxda92"; // Replace with your generated API User ID
const MOMO_API_KEY = "6f3xxxxxxxxxxxxxxxxxxxxxxxxaa"; // Replace with your generated API Key
const MOMO_CALLBACK_HOST = "https://webhook.site/xxxxxxxxxxxxxxxxxxxxx"; 
const CURRENCY = "SZL";
const ENVIRONMENT = "mtnswaziland";

// Function to get an access token from the MTN MoMo API
let getMomoAccessToken = function (nk: nkruntime.Nakama, logger: nkruntime.Logger): string | null {
    const url = `${MOMO_API_BASE_URL}/collection/token/`;
    const auth = "Basic " + nk.base64Encode(`${MOMO_API_USER_ID}:${MOMO_API_KEY}`);

    logger.info(url);

    try {
        const response = nk.httpRequest(
            url,
            "post",
            {
                "Authorization": auth,
                "Ocp-Apim-Subscription-Key": MOMO_PRIMARY_KEY,
            },
            //null
        );

        const body = JSON.parse(response.body);
        return body.access_token;
    } catch (error) {
        logger.error("Error getting MoMo access token: %v", error);
        return null;
    }
}

// Modified rpcProcessDeposit function with server-side polling
let rpcProcessDeposit: nkruntime.RpcFunction = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, payload: string): string {
    if (!ctx.userId) {
        return JSON.stringify({ success: false, error: "No user ID in context" });
    }

    try {
        const request = JSON.parse(payload);
        const amount = Number(request.amount);
        const phoneNumber = request.phoneNumber || '';

        // --- (keep your existing validation logic) ---
        if (isNaN(amount) || amount <= 0) {
            return JSON.stringify({ success: false, error: "Invalid deposit amount" });
        }
        const minDeposit = 10;
        if (amount < minDeposit) {
            return JSON.stringify({
                success: false,
                error: `Minimum deposit amount is ${minDeposit} SZL`
            });
        }
        if (phoneNumber && !isValidPhoneNumber(phoneNumber)) {
            return JSON.stringify({
                success: false,
                error: "Invalid phone number. Must be 8 digits starting with 76 or 78"
            });
        }
        // --- (end of existing validation) ---

        // 1. Get Access Token
        const accessToken = getMomoAccessToken(nk, logger);
        if (!accessToken) {
            return JSON.stringify({ success: false, error: "Could not authenticate with payment provider." });
        }

        logger.info(accessToken);
        logger.info("Got Token and displayed it");

        // 2. Initiate the payment request
        const externalId = nk.uuidv4();
        const requestUrl = `${MOMO_API_BASE_URL}/collection/v1_0/requesttopay`;
        const requestBody = {
            "amount": amount.toString(),
            "currency": CURRENCY,
            "externalId": externalId,
            "payer": { "partyIdType": "MSISDN", "partyId": `268${phoneNumber}` },
            "payerMessage": "Deposit for Crazy Eights",
            "payeeNote": "Thanks for your deposit!"
        };

        const requestHeaders = {
            "Authorization": `Bearer ${accessToken}`,
            "X-Reference-Id": externalId,
            "X-Target-Environment": ENVIRONMENT,
            "X-Callback-Url": MOMO_CALLBACK_HOST,
            "Ocp-Apim-Subscription-Key": MOMO_PRIMARY_KEY,
            "Content-Type": "application/json",
            "User-Agent": "Nakama",
        };

        logger.info("Here");
        let requestToPay = nk.httpRequest(requestUrl, "post", requestHeaders, JSON.stringify(requestBody));

        logger.info(requestToPay.code.toString());
        logger.info(requestToPay.body);

        // 3. Poll for the transaction status
        const maxRetries = 30;
        let finalStatus = "PENDING";

        for (let i = 0; i < maxRetries; i++) {
            // Wait for 2 seconds before checking the status
            const sleep = (ms: number) => new Promise(res => setTimeout(res, ms));
            sleep(2000);

            logger.info("Here1");
            const statusUrl = `${MOMO_API_BASE_URL}/collection/v1_0/requesttopay/${externalId}`;
            logger.info("Here2");
            const statusHeaders = {
                "Authorization": `Bearer ${accessToken}`,
                "X-Target-Environment": ENVIRONMENT,
                "Ocp-Apim-Subscription-Key": MOMO_PRIMARY_KEY,
            };

            const response = nk.httpRequest(statusUrl, "get", statusHeaders/*, null*/);
            const body = JSON.parse(response.body);
            finalStatus = body.status;

            if (finalStatus !== "PENDING") {
                break;
            }
        }

        // 4. Process the final status
        if (finalStatus === "SUCCESSFUL") {
            const changeset = { "szl": amount };
            const metadata = { "type": "deposit", "externalId": externalId };
            nk.walletUpdate(ctx.userId, changeset, metadata, true);

            const account = nk.accountGetId(ctx.userId);
            const updatedBalance = account.wallet["szl"] || 0;

            return JSON.stringify({ success: true, balance: updatedBalance });
        } else {
            return JSON.stringify({ success: false, error: "Transaction failed or timed out." });
        }

    } catch (error) {
        logger.error("Error processing deposit: %v", error);
        return JSON.stringify({ success: false, error: String(error) });
    }
}

@Sakhile_Mamba I thinkj this looks like an error being returned by the service you’re calling via HTTP, not a Nakama issue.