# C functions that answer questions about text

One header over a shared or a static library. Bind ThinkThen to any language that can call C.

## Install

| Channel | Note |
| --- | --- |
| `thinkthen.h + libthinkthen` | Each release ships the header, the shared library, and the static library. |

Set `THINKTHEN_API_KEY` in the environment.

## A first call

```
#include <assert.h>
#include <json-c/json.h>
#include <thinkthen.h>

int main(void) {
    thinkthen_engine *tt = thinkthen_engine_new();
    assert(tt);

    const char *ask =
        "{\"score\": \"How urgent is this?\", "
        "\"levels\": "
        "[\"Routine.\", \"Soon.\", \"Immediate.\"], "
        "\"evidence\": \""
        "Our checkout page is down and "
        "customers cannot pay.\\n\"}";
    char *urgency_call = thinkthen_call(tt, ask);
    assert(urgency_call);

    enum json_tokener_error parse_error;
    struct json_object *envelope =
        json_tokener_parse_verbose(
            urgency_call, &parse_error);
    assert(parse_error == json_tokener_success);
    assert(json_object_get_type(envelope)
        == json_type_object);

    struct json_object *urgency;
    json_bool has_value = json_object_object_get_ex(
        envelope, "value", &urgency);
    assert(has_value);
    assert(json_object_get_double(urgency) == 2.0);

    struct json_object *facts;
    json_bool has_facts = json_object_object_get_ex(
        envelope, "facts", &facts);
    assert(has_facts);
    assert(json_object_get_type(facts)
        == json_type_object);

    json_object_put(envelope);
    thinkthen_free_string(urgency_call);
    thinkthen_engine_free(tt);
    return 0;
}
```

*Build and run it beside the unpacked archive thinkthen-c/*

```
cc -std=c11 -I thinkthen-c/include \
    first-call.c -o first-call \
    $(pkg-config --cflags --libs json-c) \
    -L thinkthen-c/lib -lthinkthen \
    -Wl,-rpath,"$PWD/thinkthen-c/lib"
./first-call
```

Not sure comes back as the outcome `THINKTHEN_UNSURE`. Branch on it and send those cases to a person. Each [function page](/functions/) shows its C call.

## Run facts

A JSON call returns `{"value":...,"facts":...}`.

## Errors

A failed call returns NULL, or a code from `THINKTHEN_EUSAGE` to `THINKTHEN_EDEFECT`. `thinkthen_error_message` reads the message on the same thread.

## Settings and recording

`thinkthen_engine_new_with` takes the settings as JSON. `"record"` writes a recording to a folder. `"replay"` answers from that recording with no connection. The key stays in `THINKTHEN_API_KEY`. The [Settings](/install/settings/) page lists every setting.

## Jev, Liquid d1 and Ollama from C

C reads its backend from the environment. Set `THINKTHEN_BACKEND` to the name below. Set the backend's key variable in the shell, and the same sample asks that backend.

| Backend | Name | Key variable |
| --- | --- | --- |
| [TypeSafe Jev](/install/backends/typesafe/) | `typesafe` | `TYPESAFE_API_KEY` |
| [Liquid d1](/install/backends/liquid/) | `liquid` | `LIQUIDAI_API_KEY`, then `LIQUID_API_KEY` |
| [Ollama](/install/backends/ollama/) | `ollama` | `OLLAMA_API_KEY`. A local address needs no key. |

*Ask TypeSafe Jev.*

```
export THINKTHEN_BACKEND=typesafe
export TYPESAFE_API_KEY=...
```

*Ask Liquid d1.*

```
export THINKTHEN_BACKEND=liquid
export LIQUIDAI_API_KEY=...
```

*Ask Ollama. This block names a second port, 11535, as the site's runs do. On the default port, leave THINKTHEN_BASE_URL out.*

```
export THINKTHEN_BACKEND=ollama
export THINKTHEN_BASE_URL=http://localhost:11535/v1
```

```
#include <assert.h>
#include <string.h>
#include <thinkthen.h>

int main(void) {
    thinkthen_engine *tt = thinkthen_engine_new();
    assert(tt);

    const char *question =
        "Does the customer ask for a refund?";
    const char *broken =
        "Please refund my order. It arrived broken.";
    const char *thanks =
        "Thanks for the quick help yesterday!";

    thinkthen_answer broken_answer;
    int broken_code = thinkthen_decide(
        tt, question, broken, strlen(broken),
        &broken_answer);
    assert(broken_code == THINKTHEN_OK);
    assert(broken_answer.outcome == THINKTHEN_YES);

    thinkthen_answer thanks_answer;
    int thanks_code = thinkthen_decide(
        tt, question, thanks, strlen(thanks),
        &thanks_answer);
    assert(thanks_code == THINKTHEN_OK);
    assert(thanks_answer.outcome == THINKTHEN_NO);

    thinkthen_engine_free(tt);
    return 0;
}
```

*Build and run it beside the unpacked archive thinkthen-c/*

```
cc -std=c11 -I thinkthen-c/include \
    backends.c -o backends \
    $(pkg-config --cflags --libs json-c) \
    -L thinkthen-c/lib -lthinkthen \
    -Wl,-rpath,"$PWD/thinkthen-c/lib"
./backends
```

The configuration file's `backend` names a default backend for every run. The [Configuration](/install/configuration/#configuration-file) page shows the file.

### OpenAI Decisions API from C

OpenAI announced its Decisions API on 2026-09-29 in its [DevDay 2026 recap](https://openai.com/index/devday-2026-recap/). OpenAI has published no address, schema or price, so ThinkThen cannot call it. The [OpenAI Decisions API](/install/backends/openai/) page says what ThinkThen knows.

## What is different in C

- The JSON examples parse the `value` and `facts` members with json-c. Install its development headers and link with `pkg-config --cflags --libs json-c` beside libthinkthen.
- A failed JSON call returns NULL. A successful `value` can itself be JSON null. Typed calls use a result struct and an error code.

On GitHub: [github.com/botassembly/thinkthen](https://github.com/botassembly/thinkthen)
