Documentation de l'API de remplacement de textures#
URL de base :
https://api.ideal.house
Version : v1
Mis à jour : 2026-03-25
📖 Vue d'ensemble#
L'API de remplacement de textures permet de remplacer la texture ou le matériau d'une zone sélectionnée dans une image à l'aide d'une image de référence de style. Vous fournissez une image source, une image de référence de style qui définit la texture ou le matériau cible, ainsi qu’une image de masque qui spécifie la zone à laquelle appliquer la nouvelle texture. L'IA intègre harmonieusement la nouvelle texture dans la scène d'origine. Le flux de travail est asynchrone et comporte deux étapes :
- Créer une tâche — Soumettez votre image source, votre image de style, votre masque et vos paramètres, puis recevez un
taskId. - Interrogation périodique des résultats — Utilisez le
taskIdpour interroger l'état de la tâche et récupérer l'image résultat.
🔐 Authentification#
Toutes les requêtes API doivent être authentifiées à l'aide d'une clé API.
Incluez votre clé API dans l'en-tête de la requête :
| En-tête | Valeur |
|---|---|
APIKEY | your_api_key_here |
⚠️ Conservez votre clé API en sécurité. Ne l'exposez pas dans du code côté client ou dans des dépôts publics.
💰 Déduction de crédits#
[!WARNING] 🪙 3 crédits sont déduits lors de la création réussie de la tâche. Si la tâche échoue in fine, les crédits déduits seront automatiquement remboursés sur votre compte.
Un solde insuffisant retournera le code d'erreur9051. 📄 Consultez Référence de déduction des crédits.
| Opération | Crédits déduits |
|---|---|
| Tâche de remplacement de textures | 3 crédits |
🖼️ Format de l'image de masque#
L'image de masque définit la zone où le remplacement de texture sera appliqué.
Règles du masque :
| Couleur | Signification |
|---|---|
| ⬛ Noir | Zone à laquelle appliquer la nouvelle texture (zone à remplacer) |
| ⬜ Blanc | Zone à conserver (arrière-plan à laisser inchangé) |
⚠️ L'image de masque doit correspondre aux mêmes dimensions que l'image source (
imageUrl).
Exemple de masque :
La zone noire dans le masque définit l'emplacement où la nouvelle texture sera appliquée ; la zone blanche est l'arrière-plan à conserver.
📌 Points de terminaison de l'API#
1. Créer une tâche de remplacement de textures#
Crée une nouvelle tâche de remplacement de texture par IA et renvoie un taskId unique pour l'interrogation périodique.
Point de terminaison
POST /api/v1/textureReplacer/generate
En-têtes de la requête
| En-tête | Requis | Description |
|---|---|---|
APIKEY | ✅ Oui | Votre clé d'authentification API |
Content-Type | ✅ Oui | application/json |
Corps de la requête
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
imageUrl | string | ✅ Oui | URL de l'image source (la pièce/la scène à laquelle appliquer la texture) |
styleImageUrl | string | ✅ Oui | URL de l'image de référence de style qui définit la texture ou le matériau cible |
maskUrl | string | ⚠️ Soit maskUrl soit maskBase64 | URL de l'image de masque. Les zones noires recevront la nouvelle texture ; les zones blanches seront conservées |
maskBase64 | string | ⚠️ Soit maskUrl soit maskBase64 | Image de masque encodée en Base64 (format PNG recommandé). À utiliser lorsque vous ne pouvez pas fournir une URL hébergée |
prompt | string | ❌ Facultatif | Invite textuelle supplémentaire pour guider davantage la génération de texture |
⚠️ Au moins un des champs
maskUrloumaskBase64doit être fourni. Si les deux sont fournis,maskUrlest prioritaire.
🖼️ Exigences relatives aux images : Les images source, de style et de masque doivent utiliser les formats JPG/JPEG, PNG ou WebP. Chaque image ne doit pas dépasser 20 Mo, avec des dimensions allant de 128 × 128 px à 6,000 × 6,000 px (inclus). Les images dépassant les dimensions maximales en pixels sont automatiquement redimensionnées proportionnellement pour respecter 6,000 × 6,000 px avant traitement. Les URLs des images doivent être directement accessibles par le serveur API. Un masque Base64 est soumis aux mêmes limites d'image décodée et ne doit pas inclure de préfixe data-URL.
📥 Exemples de requête#
cURL
# Using maskUrl
curl -X POST "https://api.ideal.house/api/v1/textureReplacer/generate" \
-H "APIKEY: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "https://example.com/room.jpg",
"styleImageUrl": "https://example.com/marble-texture.jpg",
"maskUrl": "https://example.com/mask.png"
}'
# Using maskBase64 with optional prompt
curl -X POST "https://api.ideal.house/api/v1/textureReplacer/generate" \
-H "APIKEY: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "https://example.com/room.jpg",
"styleImageUrl": "https://example.com/wood-texture.jpg",
"maskBase64": "iVBORw0KGgoAAAANSUhEUgAA...",
"prompt": "natural oak wood grain texture"
}'
Java (OkHttp)
import okhttp3.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
public class TextureReplacerApiExample {
private static final String BASE_URL = "https://api.ideal.house";
private static final String API_KEY = "your_api_key_here";
public static void main(String[] args) throws IOException {
OkHttpClient client = new OkHttpClient();
// Option 1: Use maskUrl
String requestBody = """
{
"imageUrl": "https://example.com/room.jpg",
"styleImageUrl": "https://example.com/marble-texture.jpg",
"maskUrl": "https://example.com/mask.png"
}
""";
// Option 2: Use maskBase64 (encode local mask file)
// byte[] maskBytes = Files.readAllBytes(Path.of("/path/to/mask.png"));
// String maskBase64 = Base64.getEncoder().encodeToString(maskBytes);
// String requestBody = """
// {
// "imageUrl": "https://example.com/room.jpg",
// "styleImageUrl": "https://example.com/marble-texture.jpg",
// "maskBase64": "%s",
// "prompt": "natural oak wood grain texture"
// }
// """.formatted(maskBase64);
Request request = new Request.Builder()
.url(BASE_URL + "/api/v1/textureReplacer/generate")
.addHeader("APIKEY", API_KEY)
.addHeader("Content-Type", "application/json")
.post(RequestBody.create(requestBody, MediaType.parse("application/json")))
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Response: " + response.body().string());
}
}
}
Python (requests)
import requests
import base64
BASE_URL = "https://api.ideal.house"
API_KEY = "your_api_key_here"
headers = {
"APIKEY": API_KEY,
"Content-Type": "application/json"
}
# Option 1: Use maskUrl
payload = {
"imageUrl": "https://example.com/room.jpg",
"styleImageUrl": "https://example.com/marble-texture.jpg",
"maskUrl": "https://example.com/mask.png"
}
# Option 2: Use maskBase64 with optional prompt
# with open("/path/to/mask.png", "rb") as f:
# mask_base64 = base64.b64encode(f.read()).decode("utf-8")
# payload = {
# "imageUrl": "https://example.com/room.jpg",
# "styleImageUrl": "https://example.com/wood-texture.jpg",
# "maskBase64": mask_base64,
# "prompt": "natural oak wood grain texture"
# }
response = requests.post(
f"{BASE_URL}/api/v1/textureReplacer/generate",
headers=headers,
json=payload
)
data = response.json()
task_id = data.get("data")
print(f"Task ID: {task_id}")
Node.js (axios)
const axios = require('axios');
const fs = require('fs');
const BASE_URL = 'https://api.ideal.house';
const API_KEY = 'your_api_key_here';
async function createTextureReplacerTask() {
try {
// Option 1: Use maskUrl
const payload = {
imageUrl: 'https://example.com/room.jpg',
styleImageUrl: 'https://example.com/marble-texture.jpg',
maskUrl: 'https://example.com/mask.png'
};
// Option 2: Use maskBase64 with optional prompt
// const maskBuffer = fs.readFileSync('/path/to/mask.png');
// const maskBase64 = maskBuffer.toString('base64');
// const payload = {
// imageUrl: 'https://example.com/room.jpg',
// styleImageUrl: 'https://example.com/wood-texture.jpg',
// maskBase64: maskBase64,
// prompt: 'natural oak wood grain texture'
// };
const response = await axios.post(
`${BASE_URL}/api/v1/textureReplacer/generate`,
payload,
{
headers: {
'APIKEY': API_KEY,
'Content-Type': 'application/json'
}
}
);
const taskId = response.data.data;
console.log('Task ID:', taskId);
return taskId;
} catch (error) {
console.error('Error:', error.response?.data || error.message);
}
}
createTextureReplacerTask();
📤 Réponse#
Réponse de succès
{
"code": 0,
"message": "success",
"data": 1234567890123456789
}
| Champ | Type | Description |
|---|---|---|
code | integer | 0 indique le succès |
message | string | Message de réponse |
data | long | L'ID de tâche unique pour l'interrogation des résultats |
2. Obtenir le résultat de la tâche#
Récupère l'état actuel et la sortie d'une tâche de remplacement de texture précédemment créée.
Point de terminaison
GET /api/v1/textureReplacer/result
En-têtes de la requête
| En-tête | Requis | Description |
|---|---|---|
APIKEY | ✅ Oui | Votre clé d'authentification API |
Paramètres de requête
| Paramètre | Type | Requis | Description |
|---|---|---|---|
taskId | long | ✅ Oui | L'ID de tâche retourné par le point de terminaison de création |
📥 Exemples de requête#
cURL
curl -X GET "https://api.ideal.house/api/v1/textureReplacer/result?taskId=1234567890123456789" \
-H "APIKEY: your_api_key_here"
Java (OkHttp)
import okhttp3.*;
import java.io.IOException;
public class TextureReplacerResultExample {
private static final String BASE_URL = "https://api.ideal.house";
private static final String API_KEY = "your_api_key_here";
public static void main(String[] args) throws IOException {
OkHttpClient client = new OkHttpClient();
long taskId = 1234567890123456789L;
Request request = new Request.Builder()
.url(BASE_URL + "/api/v1/textureReplacer/result?taskId=" + taskId)
.addHeader("APIKEY", API_KEY)
.get()
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Response: " + response.body().string());
}
}
}
Python (requests)
import requests
import time
BASE_URL = "https://api.ideal.house"
API_KEY = "your_api_key_here"
headers = {
"APIKEY": API_KEY
}
task_id = 1234567890123456789
# Poll until task is complete
while True:
response = requests.get(
f"{BASE_URL}/api/v1/textureReplacer/result",
headers=headers,
params={"taskId": task_id}
)
data = response.json()
result = data.get("data", {})
status = result.get("status")
print(f"Status: {status}, Progress: {result.get('percentage')}%, Queue: {result.get('waitNumber')}")
if status in ("Success", "Failed"):
break
time.sleep(3) # Poll every 3 seconds
if status == "Success":
print("Result URL:", result["output"]["resultUrl"])
else:
print("Task failed")
Node.js (axios)
const axios = require('axios');
const BASE_URL = 'https://api.ideal.house';
const API_KEY = 'your_api_key_here';
async function pollResult(taskId) {
const headers = { 'APIKEY': API_KEY };
while (true) {
const response = await axios.get(
`${BASE_URL}/api/v1/textureReplacer/result`,
{
headers,
params: { taskId }
}
);
const result = response.data.data;
const { status, percentage, waitNumber } = result;
console.log(`Status: ${status} | Progress: ${percentage}% | Queue: ${waitNumber}`);
if (['Success', 'Failed'].includes(status)) {
if (status === 'Success') {
console.log('Result URL:', result.output.resultUrl);
console.log('Size:', result.output.width, 'x', result.output.height);
} else {
console.log('Task failed');
}
break;
}
// Wait 3 seconds before next poll
await new Promise(resolve => setTimeout(resolve, 3000));
}
}
pollResult(1234567890123456789n);
📤 Réponse#
Réponse de succès (tâche terminée)
{
"code": 0,
"message": "success",
"data": {
"id": 1234567890123456789,
"status": "Success",
"waitNumber": 0,
"percentage": 100,
"input": {
"imageUrl": "https://example.com/room.jpg",
"styleImageUrl": "https://example.com/marble-texture.jpg",
"maskUrl": "https://example.com/mask.png",
"prompt": "natural marble texture with grey veining"
},
"output": {
"resultUrl": "https://cdn.ideal.house/output/texture_replacer_result.jpg",
"width": 1024,
"height": 1024
}
}
}
Réponse (tâche en cours de traitement / en file d'attente)
{
"code": 0,
"message": "success",
"data": {
"id": 1234567890123456789,
"status": "Processing",
"waitNumber": 1,
"percentage": 50,
"input": {
"imageUrl": "https://example.com/room.jpg",
"styleImageUrl": "https://example.com/marble-texture.jpg",
"maskUrl": "https://example.com/mask.png"
},
"output": null
}
}
Réponse (tâche échouée)
{
"code": 0,
"message": "success",
"data": {
"id": 1234567890123456789,
"status": "Failed",
"waitNumber": 0,
"percentage": 0,
"input": {
"imageUrl": "https://example.com/room.jpg",
"styleImageUrl": "https://example.com/marble-texture.jpg",
"maskUrl": "https://example.com/mask.png"
},
"output": null
}
}
Champs de la réponse
| Champ | Type | Description |
|---|---|---|
id | long | Identifiant unique de la tâche |
status | string | État actuel de la tâche (voir État de la tâche) |
waitNumber | integer | Nombre de tâches qui précèdent cette tâche dans la file d’attente (0 signifie actuellement en traitement) |
percentage | integer | Pourcentage d'avancement de la tâche (0–100) |
input | object | Les paramètres d'entrée originaux de la tâche |
input.imageUrl | string | URL de l'image source |
input.styleImageUrl | string | URL de l'image de référence de style |
input.maskUrl | string | URL de l'image de masque (si fournie via maskUrl) |
input.prompt | string | Invite textuelle supplémentaire (si fournie) |
output | object | Résultat de la génération (disponible uniquement lorsque status vaut Success) |
output.resultUrl | string | URL pointant vers l'image résultat avec texture remplacée |
output.width | integer | Largeur de sortie en pixels |
output.height | integer | Hauteur de sortie en pixels |
📊 État de la tâche#
| État | Description |
|---|---|
Unprocessed | La tâche a été créée mais n'a pas encore démarré |
Processing | La tâche est actuellement en cours de traitement |
Success | La tâche a été terminée avec succès — la sortie est disponible |
Failed | La tâche a échoué en raison d'une erreur |
Effectuez une interrogation périodique toutes les 3-5 secondes. Consultez Limite de tâches API.
❌ Réponses d'erreur#
Toutes les réponses d'erreur partagent la même structure JSON :
{
"code": 5002,
"message": "Invalid API Key",
"data": null
}
Référence des codes d'erreur#
| Code | Nom | Description | Action suggérée |
|---|---|---|---|
1001 | FAILED | Échec de la requête (erreur générique) | Consultez le champ message pour obtenir des détails spécifiques sur l'erreur |
1003 | INTERNAL_ERROR | Erreur interne du serveur | Réessayez après un court délai ; contactez le support si l'erreur persiste |
1011 | PARAM_ERROR | Erreur de paramètre de requête — par exemple, imageUrl, styleImageUrl ou masque manquant | Assurez-vous que tous les champs obligatoires sont fournis |
5002 | API_KEY_INVALID | Clé API invalide ou manquante | Vérifiez que l'en-tête APIKEY est présent et que sa valeur est correcte |
9010 | SCAN_TEXT_ERROR | L'invite textuelle a échoué au contrôle de contenu | Modifiez l'invite pour supprimer tout contenu sensible ou interdit |
9038 | PROHIBITED_CONTENT | L'image résultat générée contient du contenu interdit | Ajustez l'invite, le style ou les entrées, puis réessayez |
9051 | COINS_NOT_ENOUGH | Crédits / pièces insuffisants | Rechargez les crédits de votre compte, puis réessayez |
📄 Pour la liste complète des codes d'erreur courants de l'API, reportez-vous à la Référence des codes d'erreur.
