Skip to main content
RapidDev - Software Development Agency
retool-integrationsREST API Resource

How to Integrate Retool with OpenAI GPT

Connect Retool to OpenAI using a REST API Resource pointed at https://api.openai.com/v1/. Authenticate with an OpenAI API key passed as a Bearer token in the Authorization header. Build AI-powered internal tools: content generation panels, customer email drafters, support ticket classifiers, and data analysis assistants that combine OpenAI's GPT models with live database queries and CRM data.

What you'll learn

  • How to create an OpenAI API key and configure a Retool REST API Resource for the OpenAI API
  • How to build a chat completions query that injects dynamic data from Retool components and database queries
  • How to construct effective system and user prompts that produce consistent, structured AI outputs
  • How to build AI-powered internal tools: email drafters, ticket classifiers, and content generators
  • How to handle OpenAI rate limits, token budgets, and streaming responses in Retool
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate17 min read20 minutesAI/MLLast updated April 2026RapidDev Engineering Team
TL;DR

Connect Retool to OpenAI using a REST API Resource pointed at https://api.openai.com/v1/. Authenticate with an OpenAI API key passed as a Bearer token in the Authorization header. Build AI-powered internal tools: content generation panels, customer email drafters, support ticket classifiers, and data analysis assistants that combine OpenAI's GPT models with live database queries and CRM data.

Quick facts about this guide
FactValue
ToolOpenAI GPT
CategoryAI/ML
MethodREST API Resource
DifficultyIntermediate
Time required20 minutes
Last updatedApril 2026

Build AI-Powered Internal Tools in Retool with OpenAI GPT

OpenAI's GPT-4o and o1 models represent a new class of capability for internal tools: the ability to process natural language, generate structured text, classify content, extract information, and provide intelligent assistance using context from your own data. Retool's REST API Resource makes connecting to OpenAI straightforward — a single configured resource gives every query in every app access to GPT-4o's capabilities, with dynamic prompts that inject real-time data from your database, CRM, or user inputs.

The most impactful AI-powered internal tools built in Retool follow a common pattern: dynamic context injection. A customer support dashboard queries a customer's order history, account status, and recent support tickets from your database — then passes that data as context into an OpenAI prompt, asking GPT-4o to draft a personalized response. A content review panel loads a draft article, injects the company style guide as a system prompt, and asks GPT-4o to score the draft against brand guidelines. A data analysis panel runs a SQL query, passes the results to OpenAI, and asks for a plain-English summary with trend identification. The power comes from combining Retool's data access capabilities with OpenAI's reasoning.

OpenAI's function calling feature (called 'tools' in the API) enables particularly sophisticated patterns where GPT-4o can request specific data from your systems as part of its reasoning. In a Retool implementation, this means a single conversational interface can dynamically fetch different database queries based on what the AI determines it needs to answer the user's question — building a natural language query interface over your internal data without hardcoded logic for every possible question.

Integration method

REST API Resource

OpenAI provides a REST API accessed at https://api.openai.com/v1/ with Bearer token authentication using your OpenAI API key. Retool connects via a REST API Resource with the API key stored in a Configuration Variable and passed as an Authorization header. Because Retool proxies all requests server-side, the OpenAI API key never reaches end users' browsers. The /v1/chat/completions endpoint is the primary integration point, accepting a messages array with system and user messages and returning AI-generated completions. Dynamic context from Retool database queries, CRM data, or form inputs can be injected into prompts using Retool's {{ }} expression syntax.

Prerequisites

  • An OpenAI account at platform.openai.com with billing configured (the API requires a paid account or active free credits)
  • An OpenAI API key created in the OpenAI Platform under API Keys (Settings → API keys → Create new secret key)
  • Basic understanding of OpenAI's chat completion format: system message (instructions), user message (input), and assistant message (response)
  • A Retool account with permission to create Resources and Configuration Variables
  • A Retool app with at least one data source (database or other API) to serve as context for AI-powered features

Step-by-step guide

1

Create an OpenAI API key and configure the Retool Resource

To access OpenAI's API, you need an API key from the OpenAI Platform. Log in to platform.openai.com and navigate to Settings → API keys in the left sidebar. Click Create new secret key. Give it a name like 'Retool Integration' and optionally restrict it to specific projects if you are using OpenAI's project-based access control. Click Create secret key and copy the key immediately — it is shown only once and starts with 'sk-'. Add billing if your account does not have credits: navigate to Settings → Billing → Payment methods. Store the API key in Retool as a Configuration Variable (Settings → Configuration Variables) named OPENAI_API_KEY marked as a secret. In Retool Resources, click Add Resource and select REST API. Name it 'OpenAI API'. Set Base URL to https://api.openai.com/v1. Under Authentication, select Bearer Token and set the token to {{ retoolContext.configVars.OPENAI_API_KEY }}. Add a default header Content-Type: application/json. Click Save. To verify the connection, create a test query: POST to /models to list available models — a successful response returns a list of model IDs including gpt-4o, gpt-4-turbo, and others your account has access to.

Pro tip: Create separate OpenAI API keys for different environments (development and production) and use Retool's resource environments feature to switch between them. Set usage limits on each key in the OpenAI Platform (API Keys → key → Set usage limits) to prevent unexpected cost spikes from runaway queries during development. Start with a $10-20 monthly limit until you have validated usage patterns.

Expected result: The OpenAI API Resource is configured in Retool with Bearer token authentication, and a test GET /models query returns a list of available model IDs confirming the API key is valid and the resource is correctly configured.

2

Build your first chat completion query

Create a Retool query that calls the OpenAI Chat Completions endpoint. In your app's Code panel, click Create new query. Select the OpenAI API resource. Set Method to POST and Path to /chat/completions. Set Body Type to JSON. The chat completions endpoint requires a model parameter and a messages array. The messages array contains objects with role ('system', 'user', or 'assistant') and content (the text). The system message sets the AI's behavior and persona; the user message provides the actual input. Configure the body: model → 'gpt-4o' (or 'gpt-4o-mini' for faster, cheaper responses), messages → an array with a system message (instructions defining what the AI should do) and a user message (the dynamic input from a Retool component), max_tokens → 500 (limits response length and controls cost), temperature → 0.7 (creativity level: 0 = deterministic, 1 = creative), and optionally response_format → { 'type': 'json_object' } if you want structured JSON output. The response object contains choices[0].message.content with the AI's response text. Create a transformer that extracts this content. Name this query 'generateAIResponse'. Set it to run manually (not on page load) since AI calls cost money and should be triggered by user intent.

openai_chat_completion.json
1// OpenAI chat completions request body
2{
3 "model": "gpt-4o",
4 "messages": [
5 {
6 "role": "system",
7 "content": "You are a helpful customer support assistant for Acme Corp. You write professional, empathetic responses to customer inquiries. Keep responses concise (under 200 words). Always acknowledge the customer's issue before providing a solution."
8 },
9 {
10 "role": "user",
11 "content": "Customer email: {{ ticketsTable.selectedRow.subject }}\n\nCustomer message: {{ ticketsTable.selectedRow.body }}\n\nCustomer account status: {{ customerData.data[0].status }}\nRecent orders: {{ JSON.stringify(recentOrders.data.slice(0, 3)) }}\n\nPlease draft a helpful response to this customer."
12 }
13 ],
14 "max_tokens": 400,
15 "temperature": 0.6
16}

Pro tip: Use gpt-4o-mini instead of gpt-4o for classification and simple structured extraction tasks — it is approximately 15x cheaper and significantly faster for high-throughput internal tools. Reserve gpt-4o for complex reasoning tasks like drafting nuanced customer communications or analyzing multi-step business logic. For reference: gpt-4o costs approximately $2.50 per 1M input tokens; gpt-4o-mini costs $0.15 per 1M input tokens.

Expected result: The generateAIResponse query returns a response object where choices[0].message.content contains the AI-generated text, and the transformer extracts this into a clean string for display in Retool components.

3

Build an AI-powered email drafter

Implement a concrete AI email drafting panel for customer support. Start with a Table component named 'ticketsTable' connected to a SQL query that fetches open support tickets from your database: SELECT id, subject, body, customer_email, created_at, status FROM support_tickets WHERE status = 'open' ORDER BY created_at DESC LIMIT 50. Add a second query 'getCustomerContext' that runs when a ticket row is selected: SELECT account_status, subscription_tier, total_orders, last_order_date FROM customers WHERE email = {{ ticketsTable.selectedRow.customer_email }}. Add a third query 'getRecentOrders' that fetches the last 3 orders for the selected customer. Now configure the generateAIResponse query to use all this context: inject ticketsTable.selectedRow.subject, ticketsTable.selectedRow.body, getCustomerContext.data[0], and a summary of getRecentOrders.data into the user message. In the UI, add a Container on the right side of the table that shows when a ticket is selected. Inside it: display the ticket subject, body, customer email, account status, and subscription tier in Text components. Below, add a 'Generate Draft Response' button that triggers generateAIResponse. After the AI responds, show the result in a Text Area component pre-populated with the AI draft. The agent can edit the draft before copying or sending. Add a 'Regenerate' button with a temperature of 0.9 for more creative rewrites. Add an event handler on successful generation to insert a log entry: INSERT INTO ai_draft_log (ticket_id, model, prompt_tokens, completion_tokens, draft_text, generated_at) VALUES (...).

openai_response_transformer.js
1// Transformer: extract AI response and token usage
2const choice = data?.choices?.[0];
3const usage = data?.usage || {};
4
5return {
6 response_text: choice?.message?.content || 'No response generated',
7 finish_reason: choice?.finish_reason || 'unknown',
8 prompt_tokens: usage.prompt_tokens || 0,
9 completion_tokens: usage.completion_tokens || 0,
10 total_tokens: usage.total_tokens || 0,
11 estimated_cost_usd: ((usage.total_tokens || 0) / 1000000 * 2.50).toFixed(6)
12};

Pro tip: Track token usage per query in a database table (ai_usage_log) to monitor cost trends over time. Include the generating user's email, the app name, the model used, and token counts. Build a simple admin chart in a separate Retool app showing daily token consumption by user and app — this helps identify power users who might be generating unusually expensive prompts and enables cost optimization before the monthly bill arrives.

Expected result: The email drafter panel shows support ticket details with customer context, generates an AI draft response when clicked, displays the draft in an editable Text Area, and logs the generation event with token usage for cost tracking.

4

Build an AI ticket classification system

Implement bulk AI classification for unprocessed support tickets using OpenAI's structured JSON output mode. Create a query 'classifyTicket' targeting POST /chat/completions with these settings: model → 'gpt-4o-mini' (sufficient for classification, much cheaper), response_format → { 'type': 'json_object' } (forces JSON output), messages → system message: 'You are a support ticket classifier. Given a support ticket, classify it and return ONLY valid JSON with these exact fields: category (one of: Billing, Technical, Account, Feature Request, Other), priority (one of: High, Medium, Low), sentiment (one of: Positive, Neutral, Negative, Frustrated), routing (one of: Engineering, Billing, Customer Success, Self-Service), confidence (0.0-1.0), and reasoning (one sentence). Return only the JSON object, no other text.' User message: 'Ticket subject: {{ selectedTicket.subject }} Ticket body: {{ selectedTicket.body }}'. Create a transformer that parses data.choices[0].message.content as JSON and returns the structured classification object. Build a 'Classify All Unclassified' JavaScript query that iterates over all unclassified tickets in batches of 5, calls classifyTicket for each, and upserts the classification results into a ticket_classifications table. Display the classifications in the main tickets Table with color-coded Tags for priority and sentiment. Add approve/override controls: a Select for each classification field that pre-populates with the AI suggestion but allows manual correction. A 'Confirm Classifications' button bulk-updates the support_tickets table with the approved values.

batch_classify_tickets.js
1// JavaScript query: batch classify tickets with OpenAI
2const unclassifiedTickets = getUnclassifiedTickets.data || [];
3const results = [];
4
5// Process in batches of 5 to manage rate limits
6for (let i = 0; i < unclassifiedTickets.length; i += 5) {
7 const batch = unclassifiedTickets.slice(i, i + 5);
8 const batchResults = await Promise.all(
9 batch.map(async ticket => {
10 try {
11 const classification = await classifyTicket.trigger({
12 additionalScope: { selectedTicket: ticket }
13 });
14 return {
15 ticket_id: ticket.id,
16 ...JSON.parse(classification.response_text),
17 tokens_used: classification.total_tokens,
18 classified_at: new Date().toISOString()
19 };
20 } catch (err) {
21 return { ticket_id: ticket.id, error: err.message };
22 }
23 })
24 );
25 results.push(...batchResults);
26 // Brief pause between batches to respect rate limits
27 if (i + 5 < unclassifiedTickets.length) {
28 await new Promise(r => setTimeout(r, 500));
29 }
30}
31
32return results;

Pro tip: OpenAI's JSON mode (response_format: { type: 'json_object' }) guarantees valid JSON output but requires you to instruct the model to produce JSON in the system or user prompt — the API enforces JSON but does not define the schema. For strict schema enforcement, consider using OpenAI's structured outputs feature (available on gpt-4o-2024-08-06+) with a JSON Schema definition in the response_format field.

Expected result: The classification panel fetches unclassified tickets, sends them to GPT-4o-mini in batches, displays AI classifications with confidence scores, and allows agents to approve or override classifications before updating the database.

5

Add usage monitoring and prompt management

To maintain cost control and improve AI output quality over time, build a usage monitoring panel and a prompt management system. Create an ai_prompts table in your database: id (serial), name (text), system_prompt (text), model (text), max_tokens (integer), temperature (decimal), created_by (text), updated_at (timestamp). This allows non-developer team members to update prompts (system messages) through a Retool form without requiring code changes. In the email drafter and classifier apps, load the active prompt from this table at app load time instead of hardcoding system messages. Create an ai_usage_log table: id (serial), query_name (text), model (text), prompt_tokens (integer), completion_tokens (integer), total_tokens (integer), estimated_cost (decimal), user_email (text), app_name (text), created_at (timestamp). After each OpenAI query, insert a row into this table using the token counts from the API response. Build an 'AI Usage Dashboard' Retool app with: daily and monthly token consumption Charts by model and app, cost tracking (estimated monthly cost based on model pricing rates), a Table of the most expensive queries by user, and a rate limit usage indicator. Add guardrails: if a single query exceeds 10,000 tokens or a user exceeds 100,000 tokens per day, show a warning notification. For complex integrations involving RAG (retrieval-augmented generation), function calling, or enterprise-scale AI workflows connecting OpenAI to multiple internal data sources, RapidDev's team can help architect and build your Retool AI-powered internal tool solution.

ai_usage_summary.sql
1-- Daily AI usage summary query
2SELECT
3 DATE(created_at) AS usage_date,
4 model,
5 app_name,
6 COUNT(*) AS api_calls,
7 SUM(prompt_tokens) AS total_prompt_tokens,
8 SUM(completion_tokens) AS total_completion_tokens,
9 SUM(total_tokens) AS total_tokens,
10 SUM(estimated_cost) AS total_cost_usd
11FROM ai_usage_log
12WHERE created_at > NOW() - INTERVAL '30 days'
13GROUP BY DATE(created_at), model, app_name
14ORDER BY usage_date DESC, total_cost_usd DESC;

Pro tip: Build prompt version control into your ai_prompts table by adding a version column and never deleting old prompt versions — only inserting new ones with an is_active flag. This lets you A/B test different system prompts (route 50% of requests to prompt v1, 50% to v2) and compare output quality and token efficiency before committing to a new prompt version across all users.

Expected result: A usage monitoring panel tracks OpenAI API costs by user, app, and model with monthly trend charts, and a prompt management interface allows authorized users to update system messages without code deployments.

Common use cases

Build an AI customer support email drafter

Create a Retool support panel where agents select a customer support ticket, view the customer's order history and previous contacts fetched from the database, and click 'Draft Response' to send the ticket content and customer context to GPT-4o. The AI generates a personalized, on-brand response draft that the agent can review, edit, and send — reducing average handle time while maintaining response quality.

Retool Prompt

Build a Retool AI email drafter. On ticket selection, load customer history from the database. A 'Draft Response' button sends the ticket content and customer data to OpenAI /v1/chat/completions with a system prompt defining the company's support tone. Display the AI draft in a Text Area for agent review and editing before sending.

Copy this prompt to try it in Retool

Build a support ticket classifier and routing panel

Create a Retool operations panel that fetches new unclassified support tickets, sends each ticket's content to OpenAI for classification (category, priority, sentiment, and routing recommendation), and displays the AI classification suggestions in a Table. Ops managers can review the classifications, approve or correct them with a click, and bulk-route tickets to the appropriate team queues.

Retool Prompt

Build a Retool ticket classifier. Fetch unclassified tickets from the support_tickets table. A 'Classify All' button sends each ticket body to OpenAI and asks for a JSON response with: category (Billing/Technical/Account/Other), priority (High/Medium/Low), sentiment (Positive/Neutral/Negative), and routing (Engineering/Billing/Customer Success). Display classifications in a Table with approve/reject buttons.

Copy this prompt to try it in Retool

Build an AI-powered data analysis assistant

Create a Retool data analysis panel where operations managers can select a dataset (sales data, user metrics, or support volumes) from a dropdown, run a SQL query to fetch the data, and send both the data and a natural language question to GPT-4o. The AI provides a plain-English analysis of trends, anomalies, and recommendations based on the actual data — acting as an on-demand analyst.

Retool Prompt

Build a Retool AI data analyst. A Select picks a report type (Sales Trend, User Growth, Support Volume). A SQL query fetches the relevant data. A Text Input accepts the manager's question ('What caused the spike last Tuesday?'). A Button sends the data + question to OpenAI chat completions. Display the AI narrative response in a formatted Text component below.

Copy this prompt to try it in Retool

Troubleshooting

OpenAI API returns 401 Unauthorized — 'Incorrect API key provided'

Cause: The API key in the OPENAI_API_KEY Configuration Variable is invalid, has been revoked, or contains extra whitespace characters. OpenAI API keys are prefixed with 'sk-' and are case-sensitive.

Solution: Navigate to platform.openai.com → API keys and verify the key is listed as active (not expired or revoked). Copy the key again carefully and update the OPENAI_API_KEY Configuration Variable in Retool Settings, ensuring no leading/trailing spaces are included. Verify the Retool resource's Bearer Token field references the Configuration Variable correctly: {{ retoolContext.configVars.OPENAI_API_KEY }}.

OpenAI returns 429 Too Many Requests — 'Rate limit reached'

Cause: Your OpenAI account has hit its requests-per-minute (RPM) or tokens-per-minute (TPM) limit. Free trial accounts and new paid accounts start with low rate limits (e.g., 3 RPM, 40,000 TPM for tier 1). Batch processing multiple tickets simultaneously often triggers rate limits.

Solution: Add delays between sequential API calls in batch processing JavaScript queries (use await new Promise(resolve => setTimeout(resolve, 500)) between requests). Enable Retool query caching (30-60 seconds) for queries that request the same classification repeatedly. Check your OpenAI account tier in platform.openai.com → Settings → Limits — rate limits increase automatically as you spend more. For high-volume use cases, request a rate limit increase through the OpenAI Platform.

OpenAI returns JSON mode responses that fail to parse — 'Unexpected token' errors

Cause: Even with response_format: { type: 'json_object' }, OpenAI occasionally returns JSON preceded by a BOM character, or the model includes backtick code fences around the JSON despite instructions not to. The JSON.parse() call fails on these malformed responses.

Solution: Add a sanitization step in your transformer before parsing: strip leading/trailing whitespace, remove markdown code fences (```json and ```), and trim BOM characters. Use a try/catch around JSON.parse() to handle parsing failures gracefully and return a fallback object with an error field that the Retool UI can display as a user-visible error message.

typescript
1// Robust JSON parsing for OpenAI responses
2const raw = data?.choices?.[0]?.message?.content || '{}';
3const cleaned = raw
4 .trim()
5 .replace(/^```json\s*/i, '')
6 .replace(/\s*```$/, '')
7 .trim();
8try {
9 return JSON.parse(cleaned);
10} catch (e) {
11 return { error: 'Failed to parse AI response', raw: cleaned };
12}

AI responses are inconsistent or off-brand — output quality varies significantly between runs

Cause: High temperature settings (above 0.8) introduce significant randomness in GPT outputs. Vague or ambiguous system prompts allow the model to interpret the task differently on each call. Missing context (no examples or constraints) leads to variable outputs.

Solution: Lower the temperature to 0.3-0.5 for tasks requiring consistency (classification, structured extraction) and 0.6-0.7 for creative tasks (email drafting). Add explicit constraints and examples to the system prompt: 'ALWAYS start the response with a direct answer', 'NEVER exceed 150 words', 'ALWAYS use the customer's first name in the greeting'. Use Retool's prompt management table to iterate on system prompts and test consistency before deploying to all users.

Best practices

  • Store the OpenAI API key in a Retool Configuration Variable marked as a secret — never paste the raw key into query bodies, JavaScript code, or resource headers directly, as it would be visible in query logs
  • Set per-user token budgets and monthly spending caps in the OpenAI Platform (API Keys → key → Set usage limits) to prevent runaway costs from unexpected query patterns during development or from a single power user
  • Use gpt-4o-mini for classification, extraction, and simple generation tasks where cost efficiency matters; reserve gpt-4o or o1 for complex reasoning tasks that genuinely require the additional capability
  • Always run OpenAI queries on manual trigger (button click) rather than on app load or on component change — AI queries cost money on every execution, and auto-running them every time a dropdown value changes can generate significant unexpected costs
  • Inject database context directly into prompts using Retool's {{ }} syntax to leverage live data in AI responses — this is the key differentiator of building AI tools in Retool versus standalone AI products, and it dramatically improves response relevance
  • Log every OpenAI API call with token counts, cost estimates, user email, app name, and timestamp in an ai_usage_log table — this enables cost attribution by team, identification of expensive prompt patterns, and budget forecasting
  • Use response_format: { type: 'json_object' } for any AI task that produces structured outputs (classification, extraction, scoring) rather than free-form text — JSON mode guarantees parseable responses and enables downstream automation based on AI decisions

Alternatives

Frequently asked questions

Does Retool have a native OpenAI connector?

No, Retool does not have a dedicated native OpenAI connector. However, connecting via a REST API Resource is straightforward — OpenAI's API follows standard REST conventions with Bearer token authentication. The setup takes under 10 minutes and gives you full access to all OpenAI endpoints: chat completions, embeddings, image generation, and the Assistants API.

How do I prevent OpenAI API costs from becoming too high in Retool?

Set spending limits in the OpenAI Platform under API Keys → key → Set usage limits — this caps monthly spend at a defined dollar amount and sends email alerts before you reach the limit. In Retool, set queries to run only on manual trigger (button click) rather than automatically. Use gpt-4o-mini for routine tasks (classification, summarization) and monitor usage in the ai_usage_log table. Log estimated_cost = (total_tokens / 1,000,000) * model_rate per query to track cost attribution by user and app.

Can I use OpenAI's function calling (tools) feature in Retool?

Yes. Add a 'tools' array to the chat completions request body with function definitions describing what data your Retool app can provide. When the AI requests a function call (choices[0].finish_reason === 'tool_calls'), extract the function name and arguments from choices[0].message.tool_calls, run the corresponding Retool query (e.g., a database lookup), append the function result to the messages array as a 'tool' role message, and send a follow-up request to the API. This multi-step flow is best implemented as a Retool Workflow with a loop that continues until finish_reason === 'stop'.

How do I build a conversational AI chatbot in Retool?

Maintain a conversation history array in a Retool State variable. Each user message appends { role: 'user', content: input } to the history. The API query sends the full history array as the messages parameter (including the system message prepended). The AI's response (choices[0].message) is appended to the history as { role: 'assistant', content: response }. A List or custom HTML component renders the conversation history. The conversation persists across query runs within the same Retool session but resets on page refresh unless stored in a database.

What is the maximum amount of text I can send to OpenAI in a single Retool query?

OpenAI's context window limits vary by model: gpt-4o supports 128,000 tokens (approximately 96,000 words), gpt-4o-mini supports 128,000 tokens as well, and o1 models support 200,000 tokens. For most Retool use cases — injecting a customer record, a few database query results, and a prompt — context limits are not a concern. For RAG (retrieval-augmented generation) use cases where you embed large documents, use OpenAI's embeddings API to chunk and retrieve only the relevant passages rather than sending full documents.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Integrations are where projects stall

We wire Retool integrations like this one every week — auth, webhooks, edge cases included. Fixed-price builds from $13K, delivered in 6–10 weeks.

Talk to an integration engineer

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.