Hice una encuesta a la comunidad FoxPro, en Patreon y en el grupo de WhatsApp, con una sola pregunta: qué es lo más difícil de tu aplicación VFP hoy. Dos de cada tres respondieron lo mismo: exponerla en la web o como API. Sacar los datos y la lógica que ya tienen a algo que un navegador, una app móvil o un programa de otra empresa puedan llamar.
Este tutorial es la respuesta a esa pregunta, hecha desde el IDE de Visual FoxPro, el de toda la vida. Al terminar tendrás una API REST que devuelve una tabla DBF en JSON y que acepta altas. El código es VFP 9 normal y corriente, y no tocas la aplicación que ya tienes: la publicas.
Parto de cero: Visual FoxPro cerrado. Cada paso dice qué pulsar, qué escribir y qué tienes que ver en pantalla. Si en algún momento lo que ves no se parece a la captura, para ahí: justo debajo te explico por qué pasa y cómo se arregla.
¿Te manejas mejor con la línea de comandos? Tienes el mismo tutorial en versión CLI: mismo proyecto, mismo resultado, con comandos que se pegan en PowerShell.
Lo que necesitas antes de empezar
- Visual FoxPro 9 SP2 instalado. FoxServer compila tu proyecto con él.
- FoxServer instalado. Con la licencia de prueba de 30 días que se emite al registrarse en el portal basta para todo lo que hay aquí. El instalador te pidió el fichero de licencia al final: si lo saltaste, vuelve a ejecutarlo.
- Un navegador, el que uses: Edge, Chrome o Firefox.
- Permiso para ejecutar programas como administrador en tu equipo. Solo hace falta para compilar, y en el paso 1 te cuento por qué.
No hace falta abrir ninguna consola ni instalar nada más.
Las tres cosas que hay que entender antes de escribir una línea
Si solo lees un recuadro de este artículo, que sea este.
1. Tu código sigue siendo tuyo. Solo se publica. FoxServer no traduce nada ni te impone un framework. Una PROCEDURE de una clase VFP se convierte en un endpoint (una dirección web que responde, como http://127.0.0.1:8099/hola) solo con añadirle una cláusula HELP:
PROCEDURE pHola(req, res) HELP "GET: hola public"
LOCAL loRes
loRes = THIS.newObject("mensaje")
loRes.mensaje = "hola"
RETURN THIS.Ok(loRes)
ENDPROCEso es una API. El resto del artículo es detalle.
2. La ruta no existe hasta que compilas. La ruta nace en esa cláusula HELP, y solo llega al servidor cuando se compila el proyecto. Es la causa número uno de «he añadido el endpoint y me da 404». Si añades una ruta y no aparece: falta compilar.
3. La llamada es síncrona. Un endpoint que tarda dos segundos, tarda dos segundos, y mientras tanto ocupa su sitio. Para consultas es cómodo; para un proceso de cuarenta segundos lo que se devuelve es un identificador y el trabajo se hace por otro lado.
Paso 1. Abrir Visual FoxPro como administrador y cargar FoxForge
FoxForge es el taller que FoxServer instala para el IDE de Visual FoxPro: un menú más en la barra, junto a File, Edit y compañía, desde el que se crean los proyectos. Se carga como cualquier .app, con un DO.
- Busca el icono de Visual FoxPro 9 que usas siempre: en el escritorio, en la barra de tareas o en el menú Inicio.
- Haz clic derecho sobre él y elige Ejecutar como administrador. Dónde está la opción depende de dónde tengas el icono:
- En el escritorio, sale directamente en el menú del clic derecho.
- En la barra de tareas, el primer clic derecho solo enseña
vfp9.exe: haz otro clic derecho sobrevfp9.exey ahí está, como en la imagen. - En el menú Inicio de Windows 11, está dentro de Más.

Según cómo tengas configurado Windows, puede que antes de abrirse te pregunte si quieres permitir que la aplicación haga cambios en el equipo. Es el Control de cuentas de usuario: si sale, responde Sí. Si no sale nada y el IDE se abre directamente, también está bien: tu Windows está configurado para no preguntar.
¿Por qué como administrador? Tu proyecto se compila como una DLL COM multihilo, la misma que harías con BUILD MTDLL. Al terminar de compilarla, Visual FoxPro la registra en Windows, y eso solo lo deja hacer a un administrador. Sin permisos, la compilación parece que termina pero deja una DLL a medias que el servidor no puede usar. Nada de lo demás necesita administrador: solo compilar.
- Con Visual FoxPro abierto, ve a la ventana de comandos. Si no la tienes a la vista: menú Window › Command Window, o Ctrl+F2.
- Escribe estas dos líneas, pulsando Intro después de cada una:
CD "C:\Program Files (x86)\FoxServer\ide"
DO FoxForge.appLas comillas del CD hacen falta porque la ruta lleva espacios. Si instalaste FoxServer en otra carpeta, cambia la ruta por la tuya: es la carpeta ide\ de la instalación.
En un segundo aparece un menú nuevo al final de la barra: FoxForge.

Si prefieres no escribir nada, el instalador de FoxServer deja en el menú Inicio, dentro de la carpeta FoxServer, un acceso Crear un proyecto (FoxForge) que abre Visual FoxPro con el menú ya puesto. Ábrelo también con clic derecho › Ejecutar como administrador.
Desde la 0.9.30, abrir un proyecto FoxServer carga FoxForge solo, si FoxServer está instalado en la máquina y el proyecto se creó o se actualizó con esa versión. Para tenerlo antes de abrir ningún proyecto, usa esas dos líneas; si lo quieres siempre, ponlas en tu programa de arranque de Visual FoxPro. Funciona igual en Visual FoxPro 9 y en VFP Advanced (VFPA).
Paso 2. FoxForge en español
FoxForge habla español e inglés, y la primera vez elige según tu Windows. Si los menús te salen en inglés:
Abre el menú FoxForge › Language › Spanish. FoxForge se acuerda de tu elección para las próximas veces.

Desde aquí te nombro los menús de FoxForge en español. Los de Visual FoxPro los dejo en inglés, que es como salen.
Paso 3. La carpeta de tus proyectos
Vamos a guardar el proyecto en C:\proyectos. El asistente del paso siguiente necesita que la carpeta ya exista, así que la creamos ahora.
Abre la ventana de comandos de Visual FoxPro, si no la tienes a la vista: menú Window › Command Window, o Ctrl+F2. Escribe esta línea y pulsa Intro:
MD C:\proyectosSi te contesta que la carpeta ya existe, no pasa nada: sigue adelante.
¿Otra carpeta? El proyecto puede ir donde tú quieras, también en tus Documentos. Aquí usamos
C:\proyectosporque es corta y así las rutas de los pasos siguientes se leen mejor.
Paso 4. Crear el proyecto
- Abre el menú FoxForge › Nuevo proyecto › Servicio web / API REST (FoxServer).

- Se abre la ventana Nuevo proyecto FoxServer. Rellénala así:
| Campo | Qué escribir |
|---|---|
| Cómo se llama | Almacen. Es el nombre de la DLL, así que no admite tildes, espacios ni símbolos: si escribes «Almacén», el asistente lo deja en Almacen y te avisa |
| Puerto | 8099 |
| Dónde lo creo | C:\proyectos\ |
| Qué va a ser | Deja marcada la primera, API REST — lo normal |
| Pedir un token para usar la API (JWT) | Déjala sin marcar |
El puerto es el «número de ventanilla» por el que tu API atenderá: 8099 es uno que casi nunca está ocupado.
Al rellenarlo, el recuadro de abajo te dice lo que va a pasar. Tiene que decir esto:
Se creará en : C:\proyectos\Almacen\
Responderá en: http://127.0.0.1:8099/
127.0.0.1 es tu propio equipo (localhost): mientras desarrollas, la API solo atiende desde tu máquina.
Si el botón Crear sigue gris, lee el recuadro: te dice qué falta. «Esa carpeta no existe» quiere decir que te saltaste el paso 3.
- Pulsa Crear.
Visual FoxPro trabaja unos segundos y te abre el Project Manager del proyecto Almacen, como cualquier otro proyecto tuyo.

Esto es lo que ha dejado en C:\proyectos\Almacen\. Es la salida de tree /f, un comando de Windows que dibuja una carpeta con todo lo que tiene dentro; puedes verlo tú mismo desde una ventana de Símbolo del sistema:

| Carpeta o fichero | Qué es |
|---|---|
Almacen.pjx | Tu proyecto, el de siempre |
build\ | Aquí saldrá la DLL, y aquí vive Almacen.json, la configuración del servidor: puerto, seguridad, registros |
logs\ | Los registros del servidor, uno por día. Vacía hasta que arranques |
src\controllers\ | Aquí van tus clases con endpoints |
src\core\ y src\lib\ | El motor de FoxServer y la librería JSON. No los toques |
src\hooks\ | La clase que se ejecuta al compilar y apunta tus rutas |
src\utils\ | PreBuild.prg y PostBuild.prg, por si quieres hacer algo antes o después de compilar |
Dentro de src\controllers\ hay un DemoController.prg con siete endpoints de ejemplo (hello, users, search…). Lo pone FoxForge para que el proyecto sirva algo desde el primer momento. No es tuyo: cuando termines este tutorial, quítalo del proyecto y vuelve a compilar, y sus rutas desaparecen.
Paso 5. El controlador de Artículos
Un controlador es una clase VFP con endpoints dentro. Vamos a crear uno para los artículos del almacén.
- En el Project Manager, abre la pestaña Code, selecciona Programs y pulsa New….
- Se abre un editor de programa vacío. Pega dentro este código entero:
*-- Articulos.prg: el controlador del tutorial.
*-- Cada PROCEDURE con su cláusula HELP es un endpoint.
DEFINE CLASS Articulos AS ApiController OLEPUBLIC
*-- Se ejecuta ANTES de cada petición: abre la tabla.
FUNCTION BeforeEndpoint(req, res)
SET DELETED ON
SET EXCLUSIVE OFF
USE articulos IN 0 SHARED AGAIN
ENDFUNC
*-- Se ejecuta DESPUÉS de cada petición: lo cierra todo.
PROCEDURE AfterEndpoint(req, res)
CLOSE DATABASES ALL
ENDPROC
*-- GET /articulos: la tabla entera en JSON.
PROCEDURE pArticulos(req, res) HELP "GET: articulos public as articulos.lista"
LOCAL lcJson
SELECT codigo, descripcion, precio, stock ;
FROM articulos ;
WHERE activo ;
ORDER BY descripcion ;
INTO CURSOR art
lcJson = THIS.TableToJson("art")
USE IN SELECT("art")
RETURN THIS.OkRaw(lcJson)
ENDPROC
*-- GET /articulos/A001: un artículo por su código.
PROCEDURE pArticulo(req, res) HELP "GET: articulos/{codigo} public as articulos.uno"
LOCAL lcCodigo, loArt
lcCodigo = req.GetParam("codigo", "")
IF EMPTY(lcCodigo)
RETURN THIS.BadRequest("Falta el código del artículo")
ENDIF
SELECT articulos
LOCATE FOR ALLTRIM(articulos.codigo) == ALLTRIM(lcCodigo)
IF !FOUND()
RETURN THIS.NotFound("No existe el artículo " + lcCodigo)
ENDIF
loArt = THIS.NewObject("codigo,descripcion,precio,stock")
loArt.codigo = ALLTRIM(articulos.codigo)
loArt.descripcion = ALLTRIM(articulos.descripcion)
loArt.precio = articulos.precio
loArt.stock = articulos.stock
RETURN THIS.Ok(loArt)
ENDPROC
*-- POST /articulos: dar de alta un artículo.
PROCEDURE pAlta(req, res) HELP "POST: articulos public as articulos.alta"
LOCAL loDatos, loNuevo, lcDesc
loDatos = req.json
IF ISNULL(loDatos) OR VARTYPE(loDatos) != "O"
RETURN THIS.BadRequest("El cuerpo tiene que ser un objeto JSON", "cuerpo_invalido")
ENDIF
lcDesc = ""
TRY
lcDesc = ALLTRIM(TRANSFORM(loDatos.descripcion))
CATCH
lcDesc = ""
ENDTRY
IF EMPTY(lcDesc)
RETURN THIS.BadRequest("Falta la descripción", "falta_descripcion")
ENDIF
loNuevo = THIS.NewObject("codigo,descripcion")
loNuevo.codigo = THIS.NewGuid()
loNuevo.descripcion = lcDesc
INSERT INTO articulos (codigo, descripcion, activo) ;
VALUES (loNuevo.codigo, loNuevo.descripcion, .T.)
RETURN THIS.Created(loNuevo)
ENDPROC
ENDDEFINE- Guárdalo con File › Save (o Ctrl+S). Te pedirá dónde, y ojo: el diálogo no se abre en la carpeta del proyecto sino en la última en la que estuvo Visual FoxPro: la
ide\de FoxServer, si hiciste elCDdel paso 1. La forma más rápida de llegar: escribeC:\proyectos\Almacen\src\controllersen la casilla del nombre y pulsa Intro, que te mete en esa carpeta. Después escribeArticulos.prgy pulsa Guardar.

- Cierra el editor. En el Project Manager, dentro de Code › Programs, tiene que aparecer
articulos.

Si no aparece en la lista, el fichero se guardó pero no quedó dentro del proyecto, y para el servidor no existe. Selecciona Programs, pulsa Add… y elige
src\controllers\Articulos.prg.
Qué hace cada parte
Léelo con calma, que es VFP de toda la vida:
DEFINE CLASS Articulos AS ApiController OLEPUBLIC. Tu clase hereda deApiController, que es donde vive todo lo deTHIS.que usas dentro.OLEPUBLICes la palabra de siempre para que una clase se pueda usar desde fuera de VFP.- La cláusula
HELPse lee así:"<VERBO>: <ruta> [public] [as <nombre>]".- El verbo es el método HTTP:
GETpara consultar yPOSTpara dar de alta. - La ruta es lo que va detrás del puerto en la dirección.
{codigo}es un trozo variable: enarticulos/A001,codigovaleA001. publicquiere decir que no hace falta token para llamarlo. Sin él, si activas la autenticación, lo pedirá.as articulos.listaes el nombre del endpoint. Ponlo siempre: si no, FoxServer se inventa uno a partir de la ruta, y dos endpointsGETsobrearticulosacaban con el mismo nombre y una línea[ERROR]en la ventana del servidor.- La cláusula
HELPno puede pasar de 255 caracteres. A 256, VFP no compila y el error no menciona la longitud por ningún lado.
- El verbo es el método HTTP:
BeforeEndpointyAfterEndpointse ejecutan antes y después de cada petición. Si tu aplicación tiene un procedimiento de arranque que poneSETs y rutas, este es su sitio.TableToJson("art")convierte un cursor entero en JSON en una sola llamada. Es la función que ahorra el noventa por ciento del trabajo de una API de consulta.OkRawy noOkenpArticulos, porqueTableToJson()ya devuelve JSON: si lo pasas porOk()se convierte otra vez y llega como un texto lleno de barras. Y al revés:Ok()con una cadena no convierte nada y devuelve{}. Pásale siempre un objeto.- Ojo al alias en
pArticulo: busca sobrearticulos, la tabla que abreBeforeEndpoint, y no sobre el cursorart. Ese cursor nace y muere dentro depArticulos. Usarlo aquí da un error «No se encuentra el alias ‘ART’», de los que cuestan un rato porque el código se lee perfectamente. reqes la petición que llega:req.GetParam("codigo", "")para los trozos de la ruta,req.GetQuery("q", "")para lo que va detrás de?,req.jsonpara el cuerpo ya convertido en objeto. El segundo argumento es el valor por defecto; sin él, te enteras tarde de que no venía.- Valida siempre lo que entra: lo que llega por la red no lo ha escrito tu formulario. Y no uses
PEMSTATUS()sobrereq.jsonpara ver si viene un campo, porque en el banco de pruebas falla. El acceso directo dentro de unTRY, como enpAlta, funciona siempre. - Lo que devuelves son códigos de estado HTTP, y cada uno tiene su función:
Ok(200),OkRaw(200),Created(201),NoContent(204),BadRequest(400),Unauthorized(401),Forbidden(403),NotFound(404) yFail(estado, mensaje, código)para cualquier otro. La lista completa, en la referencia.
Paso 6. La tabla de ejemplo
Vamos a crear la tabla articulos con dos registros para probar. Si ya tienes la tuya, en el recuadro de abajo te digo dónde tiene que estar.
Escribe estas líneas en la ventana de comandos, una a una, pulsando Intro después de cada una:
CD C:\proyectos\Almacen\build
CREATE DATABASE almacendata
CREATE TABLE articulos (codigo C(32), descripcion C(60), precio N(10,2), stock N(10,0), activo L)
INSERT INTO articulos VALUES ("A001", "Tornillo M6", 0.42, 1200, .T.)
INSERT INTO articulos VALUES ("A002", "Arandela M6", 0.11, 3400, .T.)
CLOSE DATABASES ALL
Tres detalles de estas líneas, y ninguno es capricho:
- La tabla va en
build\. El servidor busca unUSE articulossin ruta en la carpeta de la DLL. Si tu tabla ya existe en otro sitio, ábrela con su ruta completa enBeforeEndpoint, o pon ahí unSET PATH. - Va dentro de una base de datos.
descripciontiene once letras, y una tabla libre no admite nombres de campo de más de diez. Te contestaría con un error 1712 que habla de nombres duplicados y no dice nada de la longitud. YcodigoesC(32)porque es lo que mide el código que generaNewGuid()en las altas. CLOSE DATABASES ALLal final es obligatorio. El IDE abre las tablas en exclusiva (SET EXCLUSIVE ONes lo que trae por defecto), y mientras la tengas abierta aquí, el servidor no puede usarla. Sin esa línea, en el paso 9 verás un error 1705. Te lo enseño allí para que lo reconozcas.
Paso 7. Compilar
Se compila como siempre: con el botón Build… del Project Manager. Hay un solo detalle distinto de tus proyectos de siempre, y es la carpeta donde se guarda la DLL. Léelo antes de pulsar nada.
- En el Project Manager de
Almacen, pulsa Build…. - En Build Options, marca Multi-threaded COM server (dll) y Recompile All Files, y pulsa OK.

- Visual FoxPro pregunta dónde guardar la DLL y propone
almacen.dllen la carpeta del proyecto. No aceptes esa carpeta. Haz doble clic en la carpetabuildpara entrar en ella, deja el nombrealmacen.dlly pulsa Guardar.

Si guardas la DLL en la carpeta del proyecto por error. Visual FoxPro no se queja: compila, y el servidor arranca y carga tus tres endpoints como si nada. El fallo sale en la primera petición, con un error 500 que dice:
El archivo 'c:\proyectos\almacen\articulos.dbf' no existe.
Por qué pasa: el servidor busca las tablas en la carpeta donde está la DLL, y la tabla articulos está en build\. Cómo se arregla: vuelve a compilar con Build…, entra esta vez en la carpeta build al guardar y arranca el servidor de nuevo (paso 8). La DLL que quedó suelta en C:\proyectos\Almacen\ puedes borrarla.
Visual FoxPro no recuerda la carpeta: te propondrá la del proyecto cada vez que compiles, así que este aviso vale para siempre.
- Si ya habías compilado antes, Windows te preguntará si quieres reemplazar
almacen.DLL. Responde Sí.

Tarda unos segundos. Mientras compila, FoxForge lee todas las cláusulas HELP y apunta tus rutas en la configuración del servidor: ese es el momento en que tus endpoints empiezan a existir. Si no sale ninguna ventana de errores, ha compilado.
Si sale una ventana de errores, es un error de VFP en tu código, con su fichero y su línea, como en cualquier proyecto. Corrígelo y vuelve a compilar. Lo más habitual al pegar: una comilla que se ha perdido en una cláusula
HELP.
Si al terminar de compilar sale esta ventana, abriste Visual FoxPro sin administrador:

«Access to system Registry denied» quiere decir que la DLL ha salido a medias. Visual FoxPro compila, pero al final no puede registrarla en Windows y la deja incompleta: pesa unos 24 KB en lugar de más de 200 KB, y el servidor no puede usarla. Pulsa OK, cierra Visual FoxPro, vuelve a abrirlo como administrador (paso 1) y compila otra vez.
Más cómodo: que FoxForge compile por ti. Con el proyecto abierto, FoxForge › Proyecto actual › Compilar la DLL en build\, o Ctrl+F7 desde cualquier sitio del IDE. Hace lo mismo que el botón Build… pero sin preguntar nada: recompila todo, deja la DLL en build\ con el nombre del proyecto y, si el servidor estaba en marcha, lo vuelve a arrancar. Así no hay carpeta que equivocar.

Si no ves esas opciones en Proyecto actual, abriste el proyecto después de cargar FoxForge: pulsa FoxForge › Refrescar menú.
Paso 8. Arrancar el servidor
El servidor es un programa aparte, FoxServer.Host.exe, que carga tu DLL y atiende las peticiones. Arráncalo desde el menú: FoxForge › Proyecto actual › Arrancar el servidor (la misma imagen del paso 7). FoxForge sabe dónde está instalado FoxServer y dónde está la configuración de tu proyecto.
¿Prefieres la ventana de comandos? Esta línea hace lo mismo.
RUN /Nabre un programa sin esperar a que termine, y--configle dice al servidor en qué carpeta está la configuración de tu proyecto. Si instalaste FoxServer en otra carpeta, cambia la primera ruta por la carpetabin\de tu instalación.
RUN /N "C:\Program Files (x86)\FoxServer\bin\FoxServer.Host.exe" --config C:\proyectos\Almacen\buildSe abre una ventana negra: es el servidor. Al cabo de un par de segundos tiene que terminar con estas líneas:
Listening: http://127.0.0.1:8099/
Server : Almacen [api] - C:\proyectos\Almacen\build\almacen.DLL
Press Ctrl+C to stop.Un poco más arriba verás tus dos controladores cargados: DemoController con 7 endpoint(s) loaded y Articulos con 3 endpoint(s) loaded.

Deja esa ventana abierta mientras pruebas: si la cierras, se apaga la API. Cada petición que llegue dejará ahí unas líneas, que es donde mirar cuando algo no va. Para parar el servidor, pulsa Ctrl+C en ella o ciérrala.
Paso 9. Probar en el navegador
Abre tu navegador y escribe esta dirección en la barra, como si fuera una página web:
http://127.0.0.1:8099/articulosTienes que ver tu tabla en JSON, ordenada por descripción, «Arandela» antes que «Tornillo», que es lo que pide la consulta:
[{
"codigo": "A002",
"descripcion": "Arandela M6",
"precio": 0.11,
"stock": 3400
},{
"codigo": "A001",
"descripcion": "Tornillo M6",
"precio": 0.42,
"stock": 1200
}]
Ahora uno solo, por su código:
http://127.0.0.1:8099/articulos/A001{
"codigo": "A001",
"descripcion": "Tornillo M6",
"precio": 0.42,
"stock": 1200
}
Y uno que no existe, para ver el NotFound del código:
http://127.0.0.1:8099/articulos/ZZZZ{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "No existe el artículo ZZZZ",
"instance": "/articulos/ZZZZ",
"code": "not_found"
}
Ese formato es Problem Details, la RFC 9457: la forma estándar de describir un error en una API, la que ya entienden los programas que la van a llamar. El detail es tu mensaje, tal como lo escribiste en THIS.NotFound(...). Las respuestas buenas no llevan ese envoltorio: salen como las has visto arriba.
Si en vez de eso ves un error 500 con «1705»
{
"type": "about:blank",
"title": "Internal Server Error",
"status": 500,
"detail": "Internal server error: Error: .beforeendpoint c:\\proyectos\\almacen\\build\\src\\controllers\\articulos.prg Error en la línea 9 Denegado c:\\proyectos\\almacen\\build\\articulos.dbf al acceso al archivo. 1705, Error Code: 1705",
"instance": "/articulos"
}
Es la tabla, que sigue abierta en tu Visual FoxPro: te saltaste el CLOSE DATABASES ALL del paso 6. Escríbelo ahora en la ventana de comandos y recarga la página, sin tocar el servidor.
Paso 10. Dar de alta un artículo desde Visual FoxPro
Un navegador solo sabe pedir con GET. Para dar de alta hace falta un POST con el artículo dentro, y eso lo hacemos desde el propio Visual FoxPro con el objeto ServerXMLHTTP de Windows, el mismo con el que muchos ya llamáis a servicios web. Escribe estas líneas en la ventana de comandos, una a una:
oHttp = CREATEOBJECT("MSXML2.ServerXMLHTTP.6.0")
oHttp.Open("POST", "http://127.0.0.1:8099/articulos", .F.)
oHttp.SetRequestHeader("Content-Type", "application/json")
oHttp.Send('{"descripcion":"Arandela M8"}')
? oHttp.Status
? oHttp.ResponseTextEn la pantalla principal de Visual FoxPro tienen que salir un 201, que es «creado», y el artículo nuevo con su código:
201
{
"codigo": "4241c943794c45ccac61dd4af6361c44",
"descripcion": "Arandela M8"
}
Tu código será otro: es un identificador único que se genera en cada alta. Vuelve al navegador, recarga http://127.0.0.1:8099/articulos y ahí está, con precio y stock a cero porque solo mandamos la descripción.
Paso 11. Cambiar algo y volver a compilar
Así va a ser tu día a día: tocas el código, compilas y pruebas. Hay un detalle que conviene saber desde ya.
Al compilar, el servidor se para. La DLL está en uso mientras el servidor la tiene cargada, y Windows no deja sobrescribirla. FoxForge lo para por ti antes de compilar, y la ventana negra se cierra sola.
Así que el ciclo es:
- Cambia lo que quieras en
Articulos.prgy guárdalo. - Pulsa Ctrl+F7 (o FoxForge › Proyecto actual › Compilar la DLL en
build\). Compila y vuelve a arrancar el servidor él solo. - Recarga el navegador.
Si compilas con el botón Build…, el servidor no vuelve solo: entra en la carpeta build al guardar, responde Sí a reemplazar y arráncalo otra vez con FoxForge › Proyecto actual › Arrancar el servidor, o con la línea RUN /N del paso 8 (en la ventana de comandos, sube con la flecha hasta ella y pulsa Intro).

Si añades un endpoint y el navegador te da 404, falta este ciclo. Vuelve a las tres cosas del principio: la ruta no existe hasta que compilas.
Si algo no sale
| Lo que ves | Qué pasa | Qué hacer |
|---|---|---|
| El botón Crear del asistente sigue gris | Falta un dato, o la carpeta no existe | Lee el recuadro de abajo del asistente; si dice que la carpeta no existe, vuelve al paso 3 |
| Al compilar, «Access to system Registry denied» | Visual FoxPro no está abierto como administrador y la DLL ha salido a medias | Ciérralo, ábrelo como administrador (paso 1) y compila otra vez |
| La ventana negra del servidor se abre y se cierra enseguida | No encuentra la configuración, o no hay DLL | Arráncalo desde FoxForge › Proyecto actual › Arrancar el servidor; con RUN /N, revisa que la ruta de --config sea C:\proyectos\Almacen\build. Y que el paso 7 terminara sin errores |
| El navegador dice que no puede conectar | El servidor no está arrancado | Mira si la ventana negra sigue abierta; si no, repite el paso 8 |
| En Proyecto actual no salen Compilar ni Arrancar el servidor | Abriste el proyecto después de cargar FoxForge | FoxForge › Refrescar menú |
| 404 en una ruta que acabas de escribir | No has compilado desde que la añadiste | Paso 11 |
500 con «El archivo c:\proyectos\almacen\articulos.dbf no existe» | Guardaste la DLL en la carpeta del proyecto y no en build\ | Compila con Ctrl+F7, que la deja en su sitio, o con Build… entrando en la carpeta build al guardar |
| 500 con 1705 | La tabla está abierta en tu Visual FoxPro | CLOSE DATABASES ALL en la ventana de comandos |
| 500 con «No se encuentra el alias» | Usas un alias que no existe en ese endpoint | Mira el apunte del alias en el paso 5 |
| 403 llamando desde otro equipo | Es la licencia, no tu código | Mira el recuadro de abajo |
Un detalle para cuando quieras que te llamen desde otra máquina. El proyecto nace atendiendo solo en 127.0.0.1, así que desde fuera ni siquiera conecta: eso no es la licencia, es la configuración (host en build\Almacen.json). Cuando lo cambies a la IP de tu equipo, verás lo segundo: si en vez de 200 te devuelve 403, no es tu endpoint, es la licencia. Una licencia Developer solo acepta peticiones desde la propia máquina. Para servir a otras hace falta una licencia Runtime, que es la que se instala en el servidor del cliente. Mientras desarrollas no la necesitas.
Lo que has hecho, y lo que no
Has publicado una tabla de tu aplicación como API REST con tres endpoints, sin salir del IDE, sin reescribir la lógica, sin cambiar de lenguaje y sin un framework por medio. Todo lo que has escrito es VFP.
Lo que no has hecho todavía es ponerla en producción: certificado HTTPS, que el servidor arranque solo como servicio de Windows, los registros, y cómo desplegar una versión nueva sin tirar el servidor. Eso es el siguiente tutorial, porque es donde más se atasca la gente que ya tiene sistemas funcionando. Mientras tanto, la documentación de FoxServer lo cuenta por partes.
¿Te gustan las líneas de comandos? Tienes este mismo tutorial en versión CLI, con los mismos pasos convertidos en comandos que se pueden pegar y repetir.
Si algo de aquí no te sale como está escrito, escríbeme a soporte@irwinrodriguez.dev con lo que ves en pantalla. Cada salida de este artículo está copiada de una ejecución real, y si la tuya es distinta quiero saberlo.