# Introduction

The official API for Safi Ai, Voice, Speech Understanding, and much more.

Safi is a simplified Ai Assistant for everyday use. From Conversation, Research, Translation, Dictation, Speech synthesis and much more.

{% hint style="info" %}
Create Account: <https://safi.insolify.com>
{% endhint %}

### Supported Languages <a href="#get-your-api-keys" id="get-your-api-keys"></a>

Safi listens fluently and speaks the following languages:

| Language          | Listening    | Speech       |
| ----------------- | ------------ | ------------ |
| Pidgin (Nigerian) | Full Support | Full Support |
| Hausa             | Full Support | Full Support |
| Igbo              | Full Support | Full Support |
| Yoruba            | Full Support | Full Support |
| Arabic            | Full Support | Full Support |
| English           | Full Support | Full Support |
| French            | Full Support | Full Support |

### Available Voices

| ID     | Name                  | Languages                              |
| ------ | --------------------- | -------------------------------------- |
| safi   | Default Safi (Female) | All Suported                           |
| tolu   | Tolu (Female)         | Yoruba, English, Pidgin                |
| nora   | Nora (Female)         | Igbo, English, Pidgin                  |
| khadi  | Khadija (Femal)       | Hausa, Pidgin                          |
| uche   | Uche (Male)           | English, Pidgin, Igbo                  |
| khalid | Khalid (Male)         | Arabic, English, Hausa, French, Pidgin |
| yemi   | Yemi (Male)           | English, Yoruba, Pidgin                |

{% hint style="info" %}
Good to know: All APIs require authentication.
{% endhint %}

### Get your API keys <a href="#get-your-api-keys" id="get-your-api-keys"></a>

Your API requests are authenticated using API keys. Any request that doesn't include an API key and Secret key will return an error.

You can generate API keys from your Dashboard at any time.


# Authentication

Your API requests are authenticated using API keys. Any request that doesn't include an API key will return an error.  You can generate API keys from your Safi Dashboard at any time.

{% hint style="info" %}
Create Account: <https://safi.insolify.com>
{% endhint %}

### Getting Your API Keys.

1. Create an account on safiloop.com&#x20;
2. Login and Go to Dashboard
3. Navigate to Settings
4. Locate API & Secret Keys.

The APIs are authenticated with headers for every request. Look at how apikey and secret key placement is done in sample requests for each endpoint.

### Changing Your Keys&#x20;

Whenever your keys got compromised, it is important you regenerate new ones to avoid surprises.


# SDK & Packages

Fasten deployment and use of the APIs by simply installing the package for selected Stacks. Other stacks can use the API docs to develop Packages or suggest to us at safi\@insolify.com

### 1. Python

{% embed url="<https://pypi.org/project/safi>" %}
PyPi package
{% endembed %}

### 2. JavaScript NPM

{% embed url="<https://www.npmjs.com/package/safi>" %}
npm Package manager.
{% endembed %}

### 3. PHP

{% embed url="<https://packagist.org/packages/insolify/safi>" %}
packagist
{% endembed %}

### 4. C#  .NET

{% embed url="<https://www.nuget.org/packages/safi>" %}
nuget.org package
{% endembed %}

### 5. Ruby on Rails

{% embed url="<https://rubygems.org/gems/safi>" %}
ruby gems
{% endembed %}

### 6. Rust Crates

{% embed url="<https://crates.io/crates/safi>" %}
rust crates
{% endembed %}

### 7. Flutter & Dart

{% embed url="<https://pub.dev/packages/safi>" %}
pub packages
{% endembed %}

{% hint style="info" %}
Platforms/Stacks not available here can proceed to next page to integrate the RESTFUL APIs.
{% endhint %}


# Voices & Languages

Before sending requests, it is important to specify the voice and language otherwise the system will try to auto detect the language and use default voice where necessary.

### 1. Get Languages&#x20;

Safi supports multiple languages fluently. You can fetch them below and append to any request/response.

<mark style="color:green;">`GET`</mark>  `/language/list`

Headers

{% tabs %}
{% tab title="Request" %}
{% code title="" %}

```json
GET /language/list
```

{% endcode %}
{% endtab %}

{% tab title="Response" %}

<pre class="language-json"><code class="lang-json"><strong>{
</strong>    "status": "success",
    "data": [
        {
            "name": "arabic",
            "voices": [
                {
                    "id": "safi",
                    "gender": "neutral"
                },
                {
                    "id": "khadi",
                    "gender": "female"
                },
                {
                    "id": "khalid",
                    "gender": "male"
                },
                {
                    "id": "idan",
                    "gender": "male"
                }
            ],
            "listening": true,
            "text": true
        },
        {
            "name": "english",
            "voices": [
                {
                    "id": "safi",
                    "gender": "neutral"
                },
                {
                    "id": "khadi",
                    "gender": "female"
                },
                {
                    "id": "nora",
                    "gender": "female"
                },
                {
                    "id": "tolu",
                    "gender": "female"
                },
                {
                    "id": "khalid",
                    "gender": "male"
                },
                {
                    "id": "uche",
                    "gender": "male"
                },
                {
                    "id": "yemi",
                    "gender": "male"
                },
                {
                    "id": "idan",
                    "gender": "male"
                }
            ],
            "listening": true,
            "text": true
        },
        {
            "name": "french",
            "voices": [
                {
                    "id": "safi",
                    "gender": "neutral"
                },
                {
                    "id": "idan",
                    "gender": "male"
                }
            ],
            "listening": true,
            "text": true
        },
        {
            "name": "hausa",
            "voices": [
                {
                    "id": "safi",
                    "gender": "neutral"
                },
                {
                    "id": "khadi",
                    "gender": "female"
                },
                {
                    "id": "khalid",
                    "gender": "male"
                },
                {
                    "id": "idan",
                    "gender": "male"
                }
            ],
            "listening": true,
            "text": true
        },
        {
            "name": "igbo",
            "voices": [
                {
                    "id": "safi",
                    "gender": "neutral"
                },
                {
                    "id": "nora",
                    "gender": "female"
                },
                {
                    "id": "uche",
                    "gender": "male"
                },
                {
                    "id": "idan",
                    "gender": "male"
                }
            ],
            "listening": true,
            "text": true
        },
        {
            "name": "pidgin",
            "voices": [
                {
                    "id": "safi",
                    "gender": "neutral"
                },
                {
                    "id": "khadi",
                    "gender": "female"
                },
                {
                    "id": "nora",
                    "gender": "female"
                },
                {
                    "id": "tolu",
                    "gender": "female"
                },
                {
                    "id": "khalid",
                    "gender": "male"
                },
                {
                    "id": "uche",
                    "gender": "male"
                },
                {
                    "id": "yemi",
                    "gender": "male"
                },
                {
                    "id": "idan",
                    "gender": "male"
                }
            ],
            "listening": true,
            "text": true
        },
        {
            "name": "yoruba",
            "voices": [
                {
                    "id": "safi",
                    "gender": "neutral"
                },
                {
                    "id": "tolu",
                    "gender": "female"
                },
                {
                    "id": "yemi",
                    "gender": "male"
                },
                {
                    "id": "idan",
                    "gender": "male"
                }
            ],
            "listening": true,
            "text": true
        }
    ],
    "message": "Fetched Account Languages.",
    "code": 0
}
</code></pre>

{% endtab %}
{% endtabs %}

***

### 2. Get Voices

By default Safi speaks all its supported languages fluently, however, you should specify voice name if you want to customize or get a specific voice with every request.

<mark style="color:green;">`Get`</mark> `/voice/list`

Headers

| Name         | Value            |
| ------------ | ---------------- |
| Content-Type | application/json |
| apiKey       | string           |
| secret       | string           |

{% tabs %}
{% tab title="Request" %}

```json
GET /voice/list
```

{% endtab %}

{% tab title="Response" %}

```json
"status":"success",
"data": [
    {
        "id": "safi",
        "gender": "neutral"
    },
    {
        "id": "khadi",
        "gender": "female"
    },
    {
        "id": "nora",
        "gender": "female"
    },
    {
        "id": "tolu",
        "gender": "female"
    },
    {
        "id": "khalid",
        "gender": "male"
    },
    {
        "id": "uche",
        "gender": "male"
    },
    {
        "id": "yemi",
        "gender": "male"
    },
    {
        "id": "idan",
        "gender": "male"
    }
    ],
"code":0,
"message":"Fetched voices"
```

{% endtab %}
{% endtabs %}


# Simple Messaging

Safi is capable of holding intelligent conversations, sticking to a thread and responding with voice, text, audio and video.

{% hint style="info" %}
Note:  This does not save conversations. To save conversations, check "Conversation Thread" section of this documentation.
{% endhint %}

<mark style="color:yellow;">`POST`</mark> `/conversation`

**Headers**

<table><thead><tr><th>Name</th><th>Value</th></tr></thead><tbody><tr><td>Content-Type</td><td><code>application/json</code></td></tr><tr><td>apikey</td><td><pre><code>string
</code></pre></td></tr><tr><td>secret</td><td>string</td></tr></tbody></table>

**Body**

| Name             | Type   | Description      |
| ---------------- | ------ | ---------------- |
| `inlanguage`     | string | Name of the user |
| `outputlanguage` | string | Age of the user  |

**Response**

{% tabs %}
{% tab title="Request" %}

```json
{
    "inlanguage":"hausa", //The language to begin with, can be switched updated mid conversation
    "outputlanguage":"english", //The language to get response in
    "responsetype":"voice", //what you need as response. Can be voice, image, video or text. If you need voice and text use voice,text.
    "agentId":"", //If you are referring to a specific agent. Its ID
    "stream":false,
    "messages":[
        {
    "message":"Your name is Bami, you are an Ai assistant for Ashobe members.", //The message can be text or url of voice or video 
    "messagetype":"text", //The message type, if voice specify and supply in message.
    "owner":"machine", //user or machine.
    "topic":"instruction" //optional. instruction(to tell the machine who it is), change topic, refresh memory.
    },
        {
    "message":"https://safiloop.com/vm/83776377272.mp3", //The message can be text or url of voice or video 
    "messagetype":"voice", //The message type, if voice specify and supply in message.
    "owner":"machine", //user or machine.
    "topic":"instruction" //optional. instruction(to tell the machine who it is), change topic, refresh memory.
    },
        {
    "message":"https://test.com/sample.mp3", //The message can be text or url of voice or video 
    "messagetype":"voice", //The message type, if voice specify and supply in message.
    "owner":"user", //user or machine.
    "topic":"" //optional. instruction(to tell the machine who it is), change topic, refresh memory.
    },
    ] // messages, the one on top is the latest one.
}
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}


# Conversation Thread

End to End Intelligent Conversation

### 1. Start a new Conversation.

&#x20;Note: chats saving needs save to be set to true, it is false by default.

```
POST  /conversation/new
```

#### Headers

| Name         | Value            |
| ------------ | ---------------- |
| Content-Type | application/json |
| apiKey       | string           |
| secret       | string           |

#### Body

| Name           | Type    | Description                                                                    |
| -------------- | ------- | ------------------------------------------------------------------------------ |
| title          | string  | title or topic for the chat.                                                   |
| inlanguage     | string  | The language to begin with, can be switched updated mid conversation           |
| outputLanguage | string  | The language to get response in                                                |
| responsetype   | string  | Can be voice, image, video or text. If you need voice and text use voice,text. |
| agentId        | string  | If you are referring to a specific agent. Its ID                               |
| stream         | boolean |                                                                                |
| save           | number  | Chats are not saved by default.                                                |
| message        | string  | The message to begin w                                                         |
| messagetype    | string  | The message type                                                               |

{% tabs %}
{% tab title="Request" %}

```
{
    "title":"Testing you", 
    "inlanguage":"hausa",
    "outputlanguage":"english", 
    "responsetype":"text", 
    "agentId":"", 
    "stream":false,
    "save":true,
    "message":"Hello Bro", 
    "messagetype":"text",
 
}
```

{% endtab %}

{% tab title="Response" %}

{% endtab %}
{% endtabs %}

### 2. Fetch Conversations

Fetch the list of all your saved conversations.

<mark style="color:green;">`GET`</mark> `/conversations`

Headers

| Name         | Value            |
| ------------ | ---------------- |
| Content-Type | application/json |
| apiKey       | string           |
| secret       | string           |

{% tabs %}
{% tab title="Request" %}
GET /conversations
{% endtab %}

{% tab title="Response" %}

```json
{
  "data": [Array]
}
```

{% endtab %}
{% endtabs %}

***

### 2. Fetch a specific conversation

This fetches a conversation using the specified ID number

<mark style="color:green;">`GET`</mark> `/conversation/{id}`

Headers

| Name         | Value            |
| ------------ | ---------------- |
| Content-Type | application/json |
| apiKey       | string           |
| secret       | string           |

{% tabs %}
{% tab title="Request" %}

```json
GET /conversation/id
```

{% endtab %}

{% tab title="Response" %}

```json
{
  "data": {}
}
```

{% endtab %}
{% endtabs %}

***

### 4. Continue a saved conversation or thread.

description

<mark style="color:yellow;">`POST`</mark>  `/conversation/{id}`

Headers

|              |                  |
| ------------ | ---------------- |
| Content-Type | application/json |
| apiKey       | string           |
| secret       | string           |

Body

| Name         | Type             | Description                                                        |
| ------------ | ---------------- | ------------------------------------------------------------------ |
| id           | string           |                                                                    |
| inlanguage   |                  | The language for the newest message to be updated mid conversation |
| outlanguage  | string           | The language to get response in                                    |
| responsetype | string           | what you need as response. Can be voice, image, video or text.     |
| agentId      | number           | If you are referring to a specific agent. Its ID                   |
| stream       | boolean          |                                                                    |
| messages     | Array\[messages] | Array of messages, the one on top is the latest one                |

{% hint style="info" %}
Message data sample
{% endhint %}

Message

| Name        | Type   | Description                                                                         |
| ----------- | ------ | ----------------------------------------------------------------------------------- |
| message     | string | The message can be text or url of voice or video                                    |
| messagetype | string | The message type, if voice specify and supply in message.                           |
| owner       | string | user or machine.                                                                    |
| topic       | string | optional. instruction(to tell the machine who it is), change topic, refresh memory. |

***

### 5. Delete a saved conversation or thread.

<mark style="color:red;">`DELETE`</mark> `/conversation/{id}`

Headers&#x20;

| Name         | Value            |
| ------------ | ---------------- |
| Content-Type | application/json |
| apiKey       | string           |
| secret       | string           |

{% tabs %}
{% tab title="Request" %}

```json
DELETE /conversation/id
```

{% endtab %}

{% tab title="Response" %}

```json
{
    "status":"success"
}
```

{% endtab %}
{% endtabs %}


# Speech Synthesis

Send Voice notes, audio files, real-time audio and get transcription, translation or voice response.

### 1. Speech to Speech

{% hint style="info" %}
Use Case: Live translation, transcription, Intepreter, Dictation.&#x20;

Example:  Can receive speech in any of the supported languages and respond with the translation speech in other supported languages.
{% endhint %}

<mark style="color:yellow;">`POST`</mark>  `/speech`

Headers

|              |                  |
| ------------ | ---------------- |
| Content-Type | application/Json |
| apikey       | string           |
| secret       | string           |

Body

| Name         | Type                           | Description                                                                    |
| ------------ | ------------------------------ | ------------------------------------------------------------------------------ |
| speech       | {filedatabase64} or {file url} | must be .ogg, .mp3, .wav                                                       |
| inlanguage   | string                         |                                                                                |
| outlanguage  | string                         |                                                                                |
| responsetype | string                         | Can be voice, image, video or text. If you need voice and text use voice,text. |
| stream       | boolean                        |                                                                                |

{% tabs %}
{% tab title="Request" %}

```json
{
    "speech":{filedatabase64} or {file url}, 
    "inlanguage":"hausa",
    "outputlanguage":"english",
    "responsetype":"voice", 
    "stream":false
}
```

{% endtab %}

{% tab title="Response" %}

<pre class="language-json"><code class="lang-json"><strong>
</strong>{
    "status":"success",
    "content":{filedatabase64} or {file url}, //.ogg, .mp3, .wav
    "inlanguage":"hausa",
    "outputlanguage":"english",
    "responsetype":"voice", //Can be voice, image, video or text. If you need voice and text use voice,text.
    "stream":false
}
</code></pre>

{% endtab %}
{% endtabs %}

***

### 2. Speech to Text

{% hint style="info" %}
Use Case: Dictation.\
Example: Get the written transcription of speech in a language, translate it to other languages and much more.
{% endhint %}

| Name         | Value            |
| ------------ | ---------------- |
| Content-Type | application/json |
| apiKey       | string           |
| secret       | string           |

#### Body

| Name           | Type                           | Description                                                                    |
| -------------- | ------------------------------ | ------------------------------------------------------------------------------ |
| speech         | {filedatabase64} or {file url} | must be .ogg, .mp3, .wav                                                       |
| inlanguage     | string                         |                                                                                |
| outputlanguage | string                         |                                                                                |
| responsetype   | string                         | Can be voice, image, video or text. If you need voice and text use voice,text. |
| stream         | boolean                        |                                                                                |

{% tabs %}
{% tab title="Request" %}

```
{
    "speech":{filedatabase64} or {file url}, //must be .ogg, .mp3, .wav
    "inlanguage":"yoruba",
    "outputlanguage":"igbo",
    "responsetype":"text", //Can be voice, image, video or text. If you need voice and text use voice,text
    "stream":false
}

```

{% endtab %}

{% tab title="Response" %}

{% endtab %}
{% endtabs %}


# Text Synthesis

This takes in text content and gives out either text or voice depending on the request. Look at 1 & 2.

### 1. Text to Speech

{% hint style="info" %}
Use Case: Used for creating voice overs, voice translation to other languages and much more.
{% endhint %}

&#x20;<mark style="color:yellow;">`POST`</mark>  `/text`

Headers&#x20;

| Name         | Value            |
| ------------ | ---------------- |
| Content-Type | application/json |
| apikey       | string           |
| secret       | string           |

Body

| Name         | Type    | Description                                                                     |
| ------------ | ------- | ------------------------------------------------------------------------------- |
| text         | string  |                                                                                 |
| voice        | string  |                                                                                 |
| responsetype | string  | Can be voice, image, video or text.  If you need voice and text use voice,text. |
| inlanguage   | string  | input language                                                                  |
| outlanguage  | string  | Ignore if you want to get same language                                         |
| speed        | number  | 0-100. 50 is usually moderate. Its optional. "stream":false                     |
| stream       | boolean |                                                                                 |

{% tabs %}
{% tab title="200" %}

```json
{
    "text":"Good morning Here",
    "voice":"khadie",
    "responsetype":"voice", //Can be voice, image, video or text. If you need voice and text use voice,text.
    "inlanguage":"hausa",
    "outlanguage":"igbo", //Ignore if you want to get same language
    "speed":50, //0-100. 50 is usually moderate. Its optional.
    "stream":false
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

***

### 2. Text to Text

{% hint style="info" %}
Use Case:  For translation, sentence correction and more.
{% endhint %}

<mark style="color:green;">`POST`</mark> `/text`

**Headers**

| Name          | Value              |
| ------------- | ------------------ |
| Content-Type  | `application/json` |
| Authorization | `Bearer <token>`   |

**Body**

| Name   | Type   | Description      |
| ------ | ------ | ---------------- |
| `name` | string | Name of the user |
| `age`  | number | Age of the user  |

**Response**

{% tabs %}
{% tab title="200" %}

```json
{
  "id": 1,
  "name": "John",
  "age": 30
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}


