Introduction
Welcome to the Mifiel API! We at Mifiel provide a simple and robust RESTful API enabling any service or company operating in Mexico to integrate electronic signatures (using the FIEL) into their workflow.
Through Mifiel's API, you can easily manage documents and certificates within your Mifiel account.
We have language bindings in Shell, PHP, Ruby and Python! You can view code examples on the right (switch between different programming languages using the tabs on top).
API Versions
All API calls are versioned, and the current Mifiel API is v1.0. We will never introduce any breaking changes within any version, but may add new, non-breaking features and enhancements from time to time.
Sandbox enviroment
For your convenience Mifiel offers a Sandbox environment where you can confidently test your code.
To start using the API in the Sandbox environment you need to first create an account at sandbox.mifiel.com.
Once you have an account you will need an APP_ID and an APP_SECRET which you can generate in sandbox.mifiel.com/access_tokens.
Just change the www.mifiel.com for sandbox.mifiel.com in every endpoint that you use.
Production enviroment
To start using the API in the Production environment you need to first create an account at mifiel.com.
Once you have an account you will need an APP_ID and an APP_SECRET which you can generate in mifiel.com/access_tokens.
Mifiel-supported SDKs
We currently suppport Ruby, PHP and Python but are working on adding more languages.
Ruby
# Configure Mifiel gem
Mifiel.config do |config|
config.app_id = '<APP_ID>'
config.app_secret = '<APP_SECRET>'
end
Add this line to your application's Gemfile:
gem 'mifiel'
Then execute:
$ bundle
Or install it yourself as:
$ gem install mifiel
You can find the repo at github.com/Mifiel/ruby-api-client.
PHP
<?php
// include composer autoload
require 'vendor/autoload.php';
// import Mifiel Client Class
use Mifiel\ApiClient as Mifiel;
// Configure Mifiel Library
Mifiel::setTokens('APP_ID', 'APP_SECRET');
?>
The best way to install Mifiel is quickly and easily with Composer.
To install the most recent version, run the following command.
php composer.phar require mifiel/api-client
Now your composer.json has been updated automatically and you're able to require the just created vendor/autoload.php file to PSR-4 autoload the library.
You can find the repo at github.com/Mifiel/ruby-api-client.
Python
# Import the Client
from mifiel import Client
# Configure Mifiel Library, you will
# pass this to every call you make to our servers.
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
# If you want to make tests without beeing charged
# you can use our sandbox enviroment with:
client.use_sandbox
The best way to install Mifiel lib is with PIP. To install the most recent version please run the following command.
pip install mifiel
You can find the repo at github.com/Mifiel/python-api-client
Authentication
Mifiel uses SHA1 HMAC encryption to authenticate API calls. Each request has to be authenticated by following these steps:
- A canonical string is first created using your HTTP headers containing the content-type, content-MD5, request URI and the timestamp. You can replace content-type and content-MD5 with a blank string if needed. The timestamp must be a valid HTTP date. The canonical string is computed as follows:
canonical_string = 'http method,content-type,content-MD5,request URI,timestamp'
This string is then used to create the signature, which is a Base64 encoded SHA1 HMAC, using the APP_SECRET key.
This signature is then added as the
Authorization
HTTP header in the following form:
Authorization: APIAuth APP-ID:signature-from-step-2
app_id = '<APP_ID>'
app_secret = '<APP_SECRET>'
rest_request = RestClient::Request.new(
url: 'https://www.mifiel.com/api/v1/documents',
method: :get,
)
response = ApiAuth.sign!(rest_request, app_id, app_secret).execute
json_response = JSON.load(response)
Ruby Example
If you are using Ruby, we recommend using our official gem.
If you want to create your own, you can use the api-auth gem which supports many popular HTTP clients. In this example we are using the RestClient gem.
Objects
Mifiel data is structured around 3 main types of objects: Document, Certificate and Signature. You’ll find these objects in the format described below.
Document
Contains information about the PDF file being signed
{
"id": "29f3cb01-744d-4eae-8718-213aec8a1678",
"original_hash": "e1a580c27d22b4...c537bf90282a6889da",
"file_file_name": "test-pdf.pdf",
"signed_by_all": true,
"signed": true,
"signed_at": "2016-01-19T16:34:37.921Z",
"status": [1, "Firmado"],
"owner": {
"email": "signer1@email.com",
"name": "Jorge Morales"
},
"callback_url": "https://www.example.com/webhook/url",
"file": "/api/v1/documents/.../file",
"file_download": "/api/v1/documents/.../file?download=true",
"file_signed": "/api/v1/documents/.../file_signed",
"file_signed_download": "/api/v1/documents/.../file_signed?download=true",
"file_zipped": "/api/v1/documents/.../zip",
"signatures": [{
"email": "signer1@email.com",
"signed": true,
"signed_at": "2016-01-19T16:34:37.887Z",
"certificate_number": "20001000000200001410",
"tax_id": "AAA010101AAA",
"signature": "77cd5156779c..4e276ef1056c1de11b7f70bed28",
"user": {
"email": "signer1@email.com",
"name": "Jorge Morales"
}
}],
"widget_id": "ABCD1234"
}
Field | Type | Description |
---|---|---|
id | String | |
original_hash | String | Hash of the original (unsigned) document |
file_file_name | String | Name of the uploaded file |
signed_by_all | Boolean | true if all signers have signed the document |
signed_at | Date | Timestamp of date signed (when all signatures have been collected) |
already_signed | String[] | People that have signed |
has_not_signed | String[] | People that have not signed |
status | Array | [code, code_message] 0: not signed, 1: signed |
owner | Object | The owner of the document. The user who created the document. |
callback_url | String | The callback URL to be POST ed when everybody signs |
file | String | Path where the original document can be downloaded |
file_signed | String | Path where the signed file can be downloaded |
file_zipped | String | Path where the file and signed file in a zip file can be downloaded |
signatures | Object[] | Array of a Signature Model |
external_id | String | A unique id for you to identify the document in the response or fetch it |
Endorsable Document
{
"tracked": true,
"type": "promissory-note",
"transferable": true,
"asset": {
"id": "f48732f18l67612427c889ae08789032",
"address": "2N2o6xjB1K5uhjg4Zaj8z9EbnGyrqQazpwX"
}
}
An endorsable document is a specific type of document whose ownership can be transferred from one person or party to another. Some examples are promissory notes (pagarés), titles (títulos), or invoices (facturas).
You can know if a document is endorsable by checking the tracked parameter. It will be true if a document pertains to this category.
Contains the same information as the Document Model with the following extra attributes:
Field | Type | Description |
---|---|---|
tracked | boolean | Always set to true for endorsable documents. |
type | String | The document type that was specified when the endorsable document was created (currently promissory note is the only supported type) |
transferable | boolean | True if the document is able to be endorsed |
asset | Object | Information about the asset |
Asset Object
The asset object has the following attributes
Field | Type | Description |
---|---|---|
id | String | ID of the asset that is assigned to the document |
address | String | The cryptocurrency address that holds the endorsable document |
Certificate
Contains information regarding the advanced electronic signatures (e.g. FIEL) used to sign the document
{
"id": "07320f00-f504-47e0-8ff6-78378d2faca4",
"type_of": "FIEL",
"cer_hex": "308204cf30...1303030303030323",
"owner": "JORGE MORALES MENDEZ",
"tax_id": "MOMJ811012643",
"expires_at": "2017-04-28T19:43:23.000Z",
"expired": false
}
Field | Type | Description |
---|---|---|
id | String | The ID of the Certificate |
type_of | String | Type of certificate used (e.g. FIEL) |
owner | String | Name of the owner as defined in the certificate |
tax_id | String | RFC (tax ID) or other identifier of owner as defined in the certificate |
cer_hex | String | Certificate in hexadecimal |
expires_at | Date | Expiration date of the Certificate |
expired | Boolean | true if the Certificate is expired |
Signature
Contains information regarding the signers that have successfully signed the document
{
"email": "signer1@email.com",
"signed": true,
"signed_at": "2016-01-19T16:34:37.887Z",
"certificate_id": "20001000000200001410",
"tax_id": "AAA010101AAA",
"signature": "77cd5156779c..4e276ef1056c1de11b7f70bed28",
"user": {
"email": "signer1@email.com",
"name": "Signer 1"
}
}
Field | Type | Description |
---|---|---|
id | String | The ID of the Certificate used to sign |
String | Email of the signer | |
signed | Boolean | true if signed |
signed_at | Date | Timestamp of the date signed |
certificate_number | String | Certificate number assigned by the certificate authority (e.g. SAT) |
tax_id | String | RFC of the signer |
signature | String | Electronic signature on the document (in hexadecimal) |
Template
{
"id": "446e56c9-6df3-444b-ad2b-c582f1fd0dd0",
"name": "NDA",
"description": "Confidential disclosure agreement between two parties",
"has_documents": false,
"header": "The HTML header",
"content": "The HTML content",
"footer": "The HTML footer",
"csv": "https://www.mifiel.com/api/v1/templates/446e56c9-6df3-444b-ad2b-c582f1fd0dd0/generate_populated_csv"
}
{
"id": "446e56c9-6df3-444b-ad2b-c582f1fd0dd0",
"name": "Pagaré",
"description": "Pagaré between two parties",
"has_documents": false,
"header": "The HTML header",
"content": "The HTML content",
"footer": "The HTML footer",
"csv": "https://www.mifiel.com/api/v1/templates/446e56c9-6df3-444b-ad2b-c582f1fd0dd0/generate_populated_csv",
"tracked": true,
"type": "promissory-note"
}
Field | Type | Description |
---|---|---|
id | String | The ID of the Template |
name | String | The name of the Template |
description | String | The description |
hash_documents | Boolean | Whether the template has documents or not |
header | Text | The Header of the template |
content | Text | The Content of the template |
footer | Text | The Footer of the template |
tracked | Boolean | Whether the template is used to create endorsable (tracked) documents or non-endorsable documents |
type | String | Type of the template if it is tracked. For now, the only value is 'promissory-note' (pagaré) |
Signatory
{
"email": "signatory@email.com",
"name": "Signatory Name",
"tax_id": "AAA010101AAA",
"field": "beneficiary"
}
Field | Type | Description |
---|---|---|
String | The email of the signatory | |
name | String | Optional The name of the signatory |
tax_id | String | Optional The tax_id (RFC) of the signatory |
field | String | Optional The type of signatory. |
The field param is required in endorsable documents. For example in a promissory note document (created with params track: true, type: 'promissory-note'
) possible values are beneficiary and subscriber for issuing and holder and receiver for transfering.
Documents
Create a Document
Send only original_hash and name if you dont want us to have the document.
require 'mifiel'
document = Mifiel::Document.create(
track: true, # for endorsable documents only
type: 'promissory-note', # for endorsable documents only
file: 'path/to/my-file.pdf',
signatories: [{
name: 'Signer 1',
email: 'signer1@email.com',
tax_id: 'AAA010101AAA'
}, {
name: 'Signer 2',
email: 'signer2@email.com',
tax_id: 'AAA010102AAA'
}],
callback_url: 'https://www.example.com/webhook/url'
)
# if you dont want us to have the PDF, you can send us
# the original_hash and the name of the document. Both are required
file_contents = File.read('path/to/my-file.pdf')
original_hash = Digest::SHA256.hexdigest(file_contents)
document = Mifiel::Document.create(
original_hash: original_hash,
name: 'my-file.pdf'
signatories: [ ... ]
)
curl -X POST https://www.mifiel.com/api/v1/documents \
-F "file=@my-file.pdf" \
-F "signatories[0][name]=Signer 1" \
-F "signatories[0][email]=signer@email.com" \
-F "callback_url=https://www.example.com/webhook/url" \
-H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Document;
$document = new Document([
'file_path' => 'path/to/my-file.pdf',
'signatories' => [
[
'name' => 'Signer 1',
'email' => 'signer1@email.com',
'tax_id' => 'AAA010101AAA'
],
[
'name' => 'Signer 2',
'email' => 'signer2@email.com',
'tax_id' => 'AAA010102AAA'
]
]
]);
// if you dont want us to have the PDF, you can just send us
// the original_hash and the name of the document. Both are required
$document = new Document([
'original_hash' => hash('sha256', file_get_contents('path/to/my-file.pdf')),
'name' => 'my-file.pdf',
'signatories' => ...
]);
$document->save();
?>
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
signatories = [
{
'name': 'Signer 1',
'email': 'signer1@email.com',
'tax_id': 'AAA010101AAA'
},
{
'name': 'Signer 2',
'email':
'signer2@email.com',
'tax_id': 'AAA010102AAA'
}
]
document = Document.create(
client=client,
signatories=signatories,
file='test/fixtures/example.pdf'
)
# if you dont want us to have the PDF, you can just send us
# the original_hash and the name of the document. Both are required
document = Document.create(
client=client,
signatories=signatories,
dhash='some-sha256-hash'
)
Create a document to be signed by passing a PDF file.
If you are using our embedded signing widget, we suggest that you pass a File so that it can be displayed to the end user (signer) within the signing flow on your webpage. Also when using the widget you must pass the email of the signer (name is optional) so that we can send them a copy of the signed document when the signing process is complete.
HTTP Request
POST https://www.mifiel.com/api/v1/documents
Parameters
Field | Type | Description |
---|---|---|
file | String | File to be signed (The hash will be automatically extracted from the file and signed) |
original_hash | String | Optional SHA256 encoded Hash of the original, unsigned document (The hash will be signed) |
signatories | Array[Signatory] | A list of Signatory Object |
callback_url | String | Optional A Callback URL to post when the document gets signed |
external_id | String | Optional A unique id for you to identify the document in the response or fetch it |
track | Boolean | Optional true if you want your document to be andorsable. |
type | String | Optional (Required if param track is true) For now, the only value is 'promissory-note' (pagaré) |
Response
Returns a Document Model
Get a Specific Document
require 'mifiel'
document = Mifiel::Document.find('29f3cb01-744d-4eae-8718-213aec8a1678')
document.original_hash
document.file
document.file_signed
document.widget_id
# ...
curl "https://www.mfiel.com.mx/api/v1/documents/29f3cb01-744d-4eae-8718-213aec8a1678"
-H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Document;
$document = Document::find('29f3cb01-744d-4eae-8718-213aec8a1678');
$document->original_hash;
$document->file;
$document->file_signed;
# ...
?>
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
document = Document.find(client, 'id')
document.original_hash
document.file
document.file_signed
# ...
Allows you to retrieve a specific document.
HTTP Request
GET https://www.mifiel.com/api/v1/documents/:id
Response
Returns a Document Models
Get All Documents
require 'mifiel'
documents = Mifiel::Document.all
curl "https://www.mifiel.com/api/v1/documents"
-H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Document;
$documents = Document::all();
?>
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
documents = Document.all(client)
Allows you to retrieve all documents in your account.
HTTP Request
GET https://www.mifiel.com/api/v1/documents
Response
Returns an Array of Document Model
Delete a Document
require 'mifiel'
Mifiel::Document.delete('29f3cb01-744d-4eae-8718-213aec8a1678')
curl -X DELETE "https://www.mifiel.com/api/v1/documents/29f3cb01-744d-4eae-8718-213aec8a1678"
-H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Document;
Document::delete('29f3cb01-744d-4eae-8718-213aec8a1678');
?>
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
Document.delete(client, '29f3cb01-744d-4eae-8718-213aec8a1678')
Allows you to delete a specific document in your account.
HTTP Request
DELETE https://www.mifiel.com/api/v1/documents/:id
Request signature
Sends an email request for the document to be signed.
require 'mifiel'
document = Mifiel::Document.find('29f3cb01-744d-4eae-8718-213aec8a1678')
email = 'signer@email.com'
cc = ['signer@email.com', 'viewer@email.com']
document.request_signature(email, cc: cc)
curl -X POST "https://www.mifiel.com/api/v1/documents/29f3cb01-744d-4eae-8718-213aec8a1678/request_signature" \
-H "Authorization: APIAuth APP-ID:hmac-signature"
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
email = 'signer@email.com'
cc = ['signer@email.com', 'viewer@email.com']
document = Document.find(client, '29f3cb01-744d-4eae-8718-213aec8a1678')
document.request_signature(email, cc=cc)
Response from Mifiel:
{
"status": "success",
"message": "Correo enviado",
"data": {
"document": {
"id": "29f3cb01-744d-4eae-8718-213aec8a1678"
}
}
}
HTTP Request
POST https://www.mifiel.com/api/v1/documents/:id/request_signature
Parameters
Field | Type | Description |
---|---|---|
String | Email of the signer | |
cc | String | Email of any non-signing viewers that should receive a copy of the signed document |
Transfer a document
require 'mifiel'
document = Mifiel::Document.find('29f3cb01-744d-4eae-8718-213aec8a1678')
# For promissory-note the call is very simple
document.transfer(
callback_url: 'https://www.example.com/webhook/url',
receiver: 'receiver@email.com', # simple
receiver: { # if you want to ensure that the receiver has a specific tax_id (RFC)
name: 'Receiver',
email: 'receiver@email.com',
tax_id: 'AAA010102AAA'
}
)
# Or for a specific endorsable document type
document.transfer(
file: 'path/to/my-transfer-file.pdf', # required in certain endorsable document types
callback_url: 'https://www.example.com/webhook/url',
signatories: [{
name: 'Issuer',
email: 'issuer@email.com',
tax_id: 'AAA010101AAA',
field: 'issuer' # Could change depending on the endorsable document type
}, {
name: 'Receiver',
email: 'receiver@email.com',
tax_id: 'AAA010102AAA',
field: 'receiver' # Could change depending on the endorsable document type
}]
)
# Transfer using a template
document.transfer(
...
template_id: '29f3cb01-744d-4eae-8718-213aec8a1678',
fields: {
name: 'My Client Name',
date: '27 Sep 2017'
}
...
)
curl -X POST https://www.mifiel.com/api/v1/documents/29f3cb01-744d-4eae-8718-213aec8a1678/transfer \
-F "file=@my-file.pdf" \
-F "signatories[0][name]=Issuer" \
-F "signatories[0][email]=issuer@email.com" \
-F "signatories[0][field]=issuer" \
-F "signatories[1][name]=Receiver" \
-F "signatories[1][email]=receiver@email.com" \
-F "signatories[1][field]=receiver" \
-F "callback_url=https://www.example.com/webhook/url" \
-H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Document;
$document = Document::find('29f3cb01-744d-4eae-8718-213aec8a1678');
# For promissory-note the call is very simple
$document->transfer([
'callback_url': 'https://www.example.com/webhook/url',
'receiver': 'receiver@email.com', # simple
'receiver': [ # if you want to ensure that the receiver has a specific tax_id (RFC)
'name': 'Receiver',
'email': 'receiver@email.com',
'tax_id': 'AAA010102AAA'
]
])
# Or for a specific endorsable document type
$document.transfer(
'file': 'path/to/my-transfer-file.pdf', # required in certain endorsable document types
'callback_url': 'https://www.example.com/webhook/url',
'signatories': [[
'name': 'Issuer',
'email': 'issuer@email.com',
'tax_id': 'AAA010101AAA',
'field': 'issuer' # Could change depending on the endorsable document type
], [
'name': 'Receiver',
'email': 'receiver@email.com',
'tax_id': 'AAA010102AAA',
'field': 'receiver' # Could change depending on the endorsable document type
]]
)
# Transfer using a template
$document.transfer([
# ...
'template_id': '29f3cb01-744d-4eae-8718-213aec8a1678',
'fields': [
'name': 'My Client Name',
'date': '27 Sep 2017'
]
# ...
])
?>
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
document = Document.find(client, '29f3cb01-744d-4eae-8718-213aec8a1678')
# For promissory-note the call is very simple
document.transfer(
'callback_url': 'https://www.example.com/webhook/url',
'receiver': 'receiver@email.com', # simple
'receiver': { # if you want to ensure that the receiver has a specific tax_id (RFC)
'name': 'Receiver',
'email': 'receiver@email.com',
'tax_id': 'AAA010102AAA'
}
)
# Or for a specific endorsable document type
document.transfer(
'file': 'path/to/my-transfer-file.pdf', # required in certain endorsable document types
'callback_url': 'https://www.example.com/webhook/url',
'signatories': [{
'name': 'Issuer',
'email': 'issuer@email.com',
'tax_id': 'AAA010101AAA',
'field': 'issuer' # Could change depending on the endorsable document type
}, {
'name': 'Receiver',
'email': 'receiver@email.com',
'tax_id': 'AAA010102AAA',
'field': 'receiver' # Could change depending on the endorsable document type
}]
)
# Transfer using a template
document.transfer(
# ...
'template_id': '29f3cb01-744d-4eae-8718-213aec8a1678',
'fields': {
'name': 'My Client Name',
'date': '27 Sep 2017'
}
# ...
)
Endorsable documents (created with track: true
param) can be transferred to other users. To do this, the receiver must have an account in Mifiel and must have set up their account to be able to receive endorsable documents.
A transfer document is a page that is annexed to the original document that contains the terms of the agreement to endorse the document. It is signed by the owner (as well as the receiver in some cases) to acknowledge that the ownership of the document has been transferred. Mifiel generates a transfer document by default at the time of endorsement, but if you would like to use your own custom text and design, please contact us.
In the case that the receiver account is not configured, we will return an error and send an email requiring him to do so. When the receiver configures his account we will send a notification to the callback_url provided so your system knows when to retry the call again.
Use this endpoint to transfer an endorsable document.
HTTP Request
POST https://www.mifiel.com/api/v1/documents/:id/transfer
Parameters
Field | Type | Description |
---|---|---|
callback_url | String | Optional A Callback URL to post when the document gets signed |
receiver | String(email) OR Hash | Optional Receiver info, it could be an email or a hash containing name, tax_id (RFC) and email. |
file | File | Optional The Transfer File. Depending on the endorsable document type, it could be required. |
signatories | Array[Signatory] | Optional A list of Signatory Object |
template_id | String | Optional The template id that you want to use to create the File. |
fields | JSON [Hash] | Optional A hash with the fields {name: value} |
Response
Returns a Tracked Document Model
Certificates
At the moment we only support signing with the FIEL (the most frequently used advanced electronic signature in Mexico). We will soon be adding support for additional types of electronic signatures and will update the documentation as we do so.
Create a Certificate
require 'mifiel'
certificate = Mifiel::Certificate.create(
file: 'path/to/my-certificate.cer'
)
curl -X POST https://www.mifiel.com/api/v1/keys \
-F "file=@my-certificate.cer" \
-H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Certificate;
$certificate = new Certificate([
'file' => 'path/to/my-certificate.cer'
])
$certificate->save();
?>
Uploads the certificate of a signer in your account.
HTTP Request
POST https://www.mifiel.com/api/v1/keys
Parameters
Field | Type | Description |
---|---|---|
file | String | .cer File of your FIEL |
Response
Returns a Certificate Model
Get a Specific Certificate
require 'mifiel'
certificate = Mifiel::Certificate.find('07320f00-f504-47e0-8ff6-78378d2faca4')
certificate.type_of
certificate.owner
certificate.tax_id
# ...
curl "https://www.mfiel.com.mx/api/v1/keys/07320f00-f504-47e0-8ff6-78378d2faca4"
-H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Certificate;
$certificate = Certificate::find('07320f00-f504-47e0-8ff6-78378d2faca4');
$certificate->cer_hex;
$certificate->type_of;
$certificate->owner;
# ...
?>
Allows you to retrieve a specific certificate.
HTTP Request
GET https://www.mifiel.com/api/v1/keys/:id
Response
Returns a Certificate Model
Get All Certificates
require 'mifiel'
certificates = Mifiel::Certificate.all
curl "https://www.mifiel.com/api/v1/keys"
-H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Certificate;
$certificates = Certificate::all();
?>
Allows you to retrieve ALL certificates in your account.
HTTP Request
GET https://www.mifiel.com/api/v1/keys
Response
Returns an Array of a Certificate Model
Delete a Certificate
require 'mifiel'
Mifiel::Certificate.delete('07320f00-f504-47e0-8ff6-78378d2faca4')
curl -X DELETE "https://www.mifiel.com/api/v1/keys/07320f00-f504-47e0-8ff6-78378d2faca4"
-H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Certificate;
Certificate::delete('id');
?>
Allows you to delete a specific certificate in your account.
HTTP Request
DELETE https://www.mifiel.com/api/v1/keys/:id
Templates
Create a Template
require 'mifiel'
content = '<div>' \
'Name <field name="name" type="text">NAME</field>' \
'Date <field name="date" type="text">DATE</field>' \
'</div>'
template = Mifiel::Template.create(
name: 'my-company-nda',
description: 'Confidential disclosure agreement',
header: '<div>some header html</div>',
content: content,
footer: '<div>some footer html</div>'
)
curl -X POST https://www.mifiel.com/api/v1/templates \
-F "name=my-company-nda" \
-F "description=Confidential disclosure agreement" \
-F "content=<div>html content</div>" \
-H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Template;
$content = '<div>' .
'Name <field name="name" type="text">NAME</field>' .
'Date <field name="date" type="text">DATE</field>' .
'</div>'
$template = new Template([
'name' => 'my-company-nda',
'description' => 'Confidential disclosure agreement',
'header' => '<div>some header html</div>',
'content' => $content,
'footer' => '<div>some footer html</div>'
]);
$template->save();
?>
from mifiel import Template, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
content = '<div>' +
'Name <field name="name" type="text">NAME</field>' +
'Date <field name="date" type="text">DATE</field>' +
'</div>'
template = Template.create(
client=client,
name='my-company-nda',
description='Confidential disclosure agreement',
header='<div>some header html</div>',
content=content,
footer='<div>some footer html</div>'
)
Templates are a tool that allows you to create templates that have a base format. You can define fields within the html so you can then create a custumized document.
HTTP Request
POST https://www.mifiel.com/api/v1/templates
Parameters
Field | Type | Description |
---|---|---|
track | Boolean | Optional true if you want documents generated from this template to be endorsable |
type | String | Optional (Required if param track is true) For now, the only value is 'promissory-note' (pagaré) |
name | String | The name of the template |
description | String | Optional Internal description of your template |
header | Text/HTML | Optional The Header of the PDF |
content | Text/HTML | The Content of the PDF |
footer | Text/HTML | Optional The footer of the PDF |
Response
Returns a Template Model
Get a Specific Template
require 'mifiel'
template = Mifiel::Template.find('29f3cb01-744d-4eae-8718-213aec8a1678')
template.name
template.header
template.content
# ...
curl "https://www.mfiel.com.mx/api/v1/templates/29f3cb01-744d-4eae-8718-213aec8a1678"
-H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Template;
$template = Template::find('29f3cb01-744d-4eae-8718-213aec8a1678');
$template->name;
$template->header;
$template->content;
# ...
?>
from mifiel import Template, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
template = Template.find(client, 'id')
template.name
template.header
template.content
# ...
Allows you to retrieve a specific template.
HTTP Request
GET https://www.mifiel.com/api/v1/templates/:id
Response
Returns a Template Model
Get All Templates
require 'mifiel'
templates = Mifiel::Template.all
curl "https://www.mifiel.com/api/v1/templates"
-H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Template;
$templates = Template::all();
?>
from mifiel import Template, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
templates = Template.all(client)
Allows you to retrieve all templates in your account.
HTTP Request
GET https://www.mifiel.com/api/v1/templates
Response
Returns an Array of Template Models
Delete a Template
require 'mifiel'
Mifiel::Template.delete('29f3cb01-744d-4eae-8718-213aec8a1678')
curl -X DELETE "https://www.mifiel.com/api/v1/templates/29f3cb01-744d-4eae-8718-213aec8a1678"
-H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Template;
Template::delete('29f3cb01-744d-4eae-8718-213aec8a1678');
?>
from mifiel import Template, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
Template.delete(client, '29f3cb01-744d-4eae-8718-213aec8a1678')
Allows you to delete a specific template in your account.
HTTP Request
DELETE https://www.mifiel.com/api/v1/templates/:id
Template fields
Get the fields of a specific template. Use it to know what to send to generate documents with this template.
require 'mifiel'
fields = Mifiel::Template.fields('29f3cb01-744d-4eae-8718-213aec8a1678')
curl "https://www.mifiel.com/api/v1/templates/29f3cb01-744d-4eae-8718-213aec8a1678/fields" \
-H "Authorization: APIAuth APP-ID:hmac-signature"
<?php
require 'vendor/autoload.php';
use Mifiel\Template;
Template::fields('29f3cb01-744d-4eae-8718-213aec8a1678');
?>
from mifiel import Template, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
fields = Template.fields(client, '29f3cb01-744d-4eae-8718-213aec8a1678')
Response from Mifiel:
[{
"type": "text",
"name": "name",
"value": "Miguel Rodriguez"
}, {
"type": "text",
"name": "date",
"value": "15/8/2018"
}]
HTTP Request
GET https://www.mifiel.com/api/v1/templates/:id/fields
Response
Returns an array of the template fields (parsed from the HTML) where each field has the following information:
Field | Type | Description |
---|---|---|
type | String | HTML type attribute of the field |
name | String | HTML name attribute of the field |
value | String | Value which was placed between the field tag in the HTML |
Template documents
Get all the active (non deleted) documents generated from a specific template.
require 'mifiel'
documents = Mifiel::Template.documents('29f3cb01-744d-4eae-8718-213aec8a1678')
document = documents.first
# Mifiel::Document
document.id
# "abcd1234"
document.status
# [0, "Pending"]
curl "https://www.mifiel.com/api/v1/templates/29f3cb01-744d-4eae-8718-213aec8a1678/documents" \
-H "Authorization: APIAuth APP-ID:hmac-signature"
from mifiel import Template, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
documents = Template.documents(client, '29f3cb01-744d-4eae-8718-213aec8a1678')
Response from Mifiel:
[{
"id": "document-id",
"file_name": "file-name.pdf",
"status": [0, "Pending"],
"owner": {
"email": "signer1@email.com",
"name": "Jorge Morales"
},
"file": "/api/v1/documents/.../file"
}]
HTTP Request
GET https://www.mifiel.com/api/v1/templates/:id/documents
Response
Returns an array with the following information about each document:
Field | Type | Description |
---|---|---|
id | String | ID of the document |
file_name | String | Name of the template file created |
status | Array | [code, code_message] 0: not signed, 1: signed |
owner | Object | The owner of the document. The user who created the document. |
file | String | Path where the original document can be downloaded |
Generate a document from a template
require 'mifiel'
document = Mifiel::Document.create_from_template(
template_id: '29f3cb01-744d-4eae-8718-213aec8a1678',
name: 'document.pdf',
fields: {
name: 'My Client Name',
date: 'Sep 27 2017'
},
signatories: [{
name: 'Some name',
email: 'some@email.com',
tax_id: 'AAA010101AAA'
}],
callback_url: 'https://www.example.com/webhook/url',
external_id: 'unique-id'
)
# If you already have a Template instance you can also do
document = template.generate_document(
name: 'document.pdf',
fields: { ... },
...
)
# document.id
# document.original_hash
# document.signers
curl -X POST "https://www.mifiel.com/api/v1/templates/29f3cb01-744d-4eae-8718-213aec8a1678/generate_document" \
-F "namme='My Client Name'" \
-F "fields[name]=My Client Name" \
-F "fields[date]=Sep 27 2017" \
-F "signatories[0][name]=Some name" \
-F "signatories[0][email]=some@email.com" \
-F "signatories[0][tax_id]=AAA010101AAA" \
-H "Authorization: APIAuth APP-ID:hmac-signature"
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
args = {
'template_id': '29f3cb01-744d-4eae-8718-213aec8a1678',
'name': 'My NDA',
'fields': {
'name': 'My Client Name',
'date': 'Sep 27 2017'
},
'signatories': [{
'name': 'Some name',
'email': 'some@email.com',
'tax_id': 'AAA010101AAA'
}],
'callback_url': 'https://www.example.com/webhook/url',
'external_id': 'unique-id'
}
document = Document.create_from_template(client, args)
<?php
require 'vendor/autoload.php';
use Mifiel\Document;
$args = [
'template_id' => '29f3cb01-744d-4eae-8718-213aec8a1678',
'name' => 'My NDA',
'fields' => [
'name' => 'My Client Name',
'date' => 'Sep 27 2017'
],
'signatories' => [[
'name' => 'Some name',
'email' => 'some@email.com',
'tax_id' => 'AAA010101AAA'
]],
'callback_url' => 'https://www.example.com/webhook/url',
'external_id' => 'unique-id'
]
$document = Document.create_document($args)
?>
HTTP Request
POST https://www.mifiel.com/api/v1/templates/:id/generate_document
Parameters
Field | Type | Description |
---|---|---|
track | Boolean | Optional true if you want your document to be endorsable |
type | String | Optional (Required if param track is true) For now, the only value is 'promissory-note' (pagaré) |
name | String | Optional The name of the document |
fields | JSON [Hash] | A hash with the fields {name: value} |
signatories | Array[Signatory] | A list of Signatory Object |
callback_url | String | Optional A Callback URL to post when the document gets signed |
external_id | String | Optional A unique id for you to identify the document in the response or fetch it |
Response
Returns a Document Model
Generate several documents from a template
require 'mifiel'
args = {
template_id: '29f3cb01-744d-4eae-8718-213aec8a1678',
identifier: 'name',
callback_url: 'https://www.my-site.com/documents-ready',
documents: [{
fields: {
name: 'My Client Name',
date: 'Sep 27 2017'
},
signatories: [{
name: 'Some Name',
email: 'some@email.com',
tax_id: 'AAA010101AAA'
}],
callback_url: 'https://www.my-site.com/sign-webhook',
external_id: 'unique-id'
}]
}
response = Mifiel::Document.create_many_from_template(args)
response.status == 'success'
from mifiel import Document, Client
client = Client(app_id='APP_ID', secret_key='APP_SECRET')
args = {
'template_id': '29f3cb01-744d-4eae-8718-213aec8a1678',
'identifier': 'name',
'callback_url': 'https://www.my-site.com/documents-ready',
'documents': [{
'fields': {
'name': 'My Client Name',
'date': 'Sep 27 2017'
},
'signatories': [{
'name': 'Some Name',
'email': 'some@email.com',
'tax_id': 'AAA010101AAA'
}],
'callback_url': 'https://www.my-site.com/sign-webhook',
'external_id': 'unique-id'
}]
}
documents = Document.create_many_from_template(client, template_id, identifier, docs)
<?php
require 'vendor/autoload.php';
use Mifiel\Document;
$args = [
'template_id' => '29f3cb01-744d-4eae-8718-213aec8a1678',
'identifier' => 'name',
'callback_url' => 'https://www.my-site.com/documents-ready',
'documents' => [{
'fields' => {
'name' => 'My Client Name',
'date' => 'Sep 27 2017'
},
'signatories' => [{
'name' => 'Some Name',
'email' => 'some@email.com',
'tax_id' => 'AAA010101AAA'
}],
'callback_url' => 'https://www.my-site.com/sign-webhook',
'external_id' => 'unique-id'
}]
]
$documents = Document.create_many_from_template($args)
?>
The generation of documents runs in the background. We will respond with 200 (OK) and start generating the documents. When our servers finish, we will POST you to the provided callback_url
with a list of the created documents.
HTTP Request
POST https://www.mifiel.com/api/v1/templates/:id/generate_documents
Response from Mifiel:
{ "status": "success" }
When the documents are ready, we will send you a POST to the callback_url with the following params:
[{
"id": "d6793b57-9101-4ce3-ae0d-e51868f3fdf9",
"folio": "{asset_id}|{address}",
"signers": [{
"name": "Some Name",
"email": "some@email.com",
"tax_id": "AAA010101AAA",
"widget_id": "d6793b57-9101-4ce3-ae0d-e51868f3fdf9"
}],
"file_name": "NDA-My-Client-Name.pdf",
"callback_url": "https://www.my-site.com/webhook",
"external_id": "unique-id"
}]
Parameters
Field | Type | Description |
---|---|---|
identifier | String | Optional A field name to use in the document name e.g "name" will append the field "name" to the document name "My-NDA-My-Client-Name.pdf" |
callback_url | String | A Callback URL to POST when all documents have been created |
documents | Array[Document] | Array of documents to create |
Documents Param
Field | Type | Description |
---|---|---|
name | Hash | The name of the document eg. document.pdf |
fields | Hash | Hash of key, value of each field {field_name: 'Field Content'} |
signatories | Array[Signatory] | A list of Signatory Object |
callback_url | String | Optional A Callback URL to post when the document gets signed |
external_id | String | Optional A unique id for you to identify the document in the response or fetch it |
Embedded Signing
Widget
Copy this code and paste it just before the </body> tag.
<script type="text/javascript">
window.mifiel=window.mifiel||[],function(){"use strict";for(var e=["widget"],i=function(e){return function(){window.mifiel.push([e].concat(Array.prototype.slice.call(arguments,0)))}},t=0;t<e.length;t++){var n=e[t];window.mifiel[n]||(window.mifiel[n]=i(n))}if(!document.getElementById("mifiel-js")){var r=document.createElement("script"),o=document.getElementsByTagName("script")[0];r.type="text/javascript",r.id="mifiel-js",r.async=!0,r.src="https://www.mifiel.com/sign-widget-v1.0.0.js",o.parentNode.insertBefore(r,o)}}();
</script>
Then insert the widget in the desired view (page) by including the following snippet:
<script type="text/javascript">
window.mifiel.widget({
widgetId: 'c8aa73d1-db06-4d18-9f56-196b00f6eb69',
appendTo: 'id-of-the-element-to-append',
successBtnText: 'Proceed to next step'
});
</script>
The widget is an embedded signing tool that we have created to allow your users to sign documents in an iFrame within your page. By embedding this tool, your users can sign seamlessly without having to leave the flow of your website.
Note: The signers do not have to have an account in mifiel.com
To begin, you have to copy and paste our code snippet (shown to your right) into the code of the page where the signing flow will take place.
You can also find the code snippet here.
Options
Field | Type | Default | Description |
---|---|---|---|
widgetId | String | Widget ID. You can get it with document.widget_id in Ruby |
|
appendTo | String | body | ID of the element in the page |
successBtnText | String | 'OK' | Text of the button at the end of the signing flow. When the user click |
Base64 | null | Optional PDF in Base64 if you did not send us the PDF when you created the document. | |
color | String | 37BC9B | Optional Custom color in hexadecimal (e.g. 555555) to personalize the look and feel of your widget. Typically the primary color of your app. |
width | String | 100% | Optional Width of the widget [px or %] |
height | String | 1100 | Optional Height of the widget [px] |
Events
Listen for Mifiel events:
<script type="text/javascript">
window.addEventListener('message', function (e) {
console.log(e);
// accept messages from known hosts only
// change to https://stageex.mifiel.com if necessary
if (e.origin !== 'https://www.mifiel.com') {
return;
}
// We will always send an object
if (typeof e.data !== 'object') {
return;
}
// document signed succesfully
if (e.data.eventType === 'mifiel.widget.success') {
var data = e.data,
doc = data.document,
signature = data.signature;
// doc.original_hash;
// doc.file_signed;
}
// Event errors
if (e.data.eventType === 'mifiel.widget.error') {
var error = e.data.error;
// error.code => 1001
// error.message => 'Invalid PDF, the pdf param has no data'
}
}, false);
</script>
We will send a postMessage to your page to notify any of the events listed below.
In order to secure the events sent by the widget you must verify that the event is coming from our servers.
You can identify the events by e.data.eventType. The success event will have "mifiel.widget.success" and the error events will have "mifiel.widget.error".
Success event
We will send the document json object and the signature of the user.
Error events
Error events have the property eventType set as "mifiel.widget.error" and a error object (e.data.error) with code and message properties:
Widget setup error events
Event | Code | Message |
---|---|---|
Empty PDF | 1001 | Invalid PDF, the pdf param has no data |
Hashes do not match | 1002 | Invalid PDF, the provided pdf param is not the same as the uploaded one |
Note: We send this errors only when you did not send us the PDF when the document was created.
User error events
Event | Code | Message |
---|---|---|
Invalid Certificate | 2001 | Certificate is not valid |
Invalid Private Key | 2002 | Invalid Private Key |
Invalid Pasword | 2003 | Invalid password |
Files do not match | 2004 | .key file does not belong to the .cer file |
Server error events
Event | Code | Message |
---|---|---|
Signature failure | 3002 | Fail to sign document |
Embedded Signing Flow
Following is a more detailed explanation of the steps involved in requesting and executing signatures within the embedded signing widget.
The first step is to create a Document in your backend with the API_ID and APP_SECRET. You must pass the PDF file that is being signed, along with the following parameters: webhook (callback_url) and the email and name (optional) of each signer.
Mifiel will return a Widget ID in the response, which you will then need to pass to the widget (running on your website's front-end).
The signature process then takes place within your website. The signer will be able to preview the document, select the files of their FIEL, and enter the password of their FIEL to sign (during this process Mifiel will be verifying that the FIEL is valid and not expired).
If successful, the signer will be presented with a page explaining that the signing was successful and that they will receive an email with the signed document. We will also display a confirmation button (e.g. 'Proceed to next step') which will return the user to the flow of your website.
Mifiel will then
POST
the document information to the webhook specified by you (in Step 1): electronic signature of the document, timestamp of signature, the signature page, and information regarding the public certificate(s) used to sign the document.
Endorsables setup
User account setup
Every user (issuer or receiver) of an endorsable document must set up his account. During this setup process, we will use the user's FIEL/e.firma to derive a set of cryptocurrency addresses where the assets (the endorsable documents) will be stored.
The widget is an embedded tool to setup the required private keys that generate the addresses. By embedding this tool, your users can setup their account without having to leave the flow of your website.
The flow to embed this tool into your site is: 1. Create a Setup widget_id on our server for your user. 2. Save the widget_id in your database so you can access it later. 3. Use the widget_id in the setup-snippet. An iframe will be placed within your site where your user would drag his FIEL and a backup certificate. 4. When the setup is complete, the iframe will trigger an event so you can redirect the user to the next step in your flow.
Require a setup widget id
HTTP Request
POST https://www.mifiel.com/api/v1/users/setup-widget
Parameters
Field | Type | Description |
---|---|---|
String | Email of the user | |
tax_id | String | Optional Tax Id (RFC) of the user |
callback_url | String | Optional URL where we will POST when the user completes the process |
Response
Field | Type | Description |
---|---|---|
widget_id | String | Widget Id to be used on the snippet |
User account setup widget
Options
Field | Type | Default | Description |
---|---|---|---|
widgetId | String | Widget ID. | |
appendTo | String | body | ID of the element in the page |
successBtnText | String | 'OK' | Text of the button at the end of the setup flow. When the user clicks, will trigger an event so you can cach it. |
color | String | 37BC9B | Optional Custom color in hexadecimal (e.g. 555555) to personalize the look and feel of your widget. Typically the primary color of your app. |
width | String | 100% | Optional Width of the widget [px or %] |
height | String | 1100 | Optional Height of the widget [px] |
Events
Listen for Mifiel events:
<script type="text/javascript">
window.addEventListener('message', function (e) {
console.log(e);
// accept messages from known hosts only
// change to https://app-stageex.mifiel.com if necessary
if (e.origin !== 'https://app.mifiel.com') {
return;
}
// We will always send an object
if (typeof e.data !== 'object') {
return;
}
// setup completed
if (e.data.eventType === 'mifiel.setup-widget.success') {
var data = e.data,
doc = data.document
}
// Event errors
if (e.data.eventType === 'mifiel.setup-widget.error') {
var error = e.data.error;
// error.code
// error.message
}
}, false);
</script>
We will send a postMessage to your page to notify any of the events listed below.
In order to secure the events sent by the widget you must verify that the event is coming from our servers.
You can identify the events by e.data.eventType. The success event will have "mifiel.setup-widget.success" and the error events will have "mifiel.setup-widget.error".
Success event
We will send the document json object and the signature of the user.
Error events
Error events have the property eventType set as "mifiel.setup-widget.error" and a error object (e.data.error) with code and message properties:
User error events
Event | Code | Message |
---|---|---|
Invalid Certificate | 2001 | Certificate is not valid |
Invalid Private Key | 2002 | Invalid Private Key |
Invalid Pasword | 2003 | Invalid password |
Files do not match | 2004 | .key file does not belong to the .cer file |
Server error events
Event | Code | Message |
---|---|---|
Setup failure | 3002 | Fail to setup user |
Errors
Error codes
Mifiel API uses the following error codes:
Error Code | Meaning |
---|---|
400 | Bad Request -- Your request had an error. (more info in the errors response param) |
401 | Unauthorized -- Your authorization header is wrong. |
402 | Payment Required -- Your request requires a paid plan. If you already have a plan, it may have expired. |
404 | Not Found -- The specified object could not be found. |
405 | Method Not Allowed -- You tried to access an invalid method. |
406 | Not Acceptable -- You requested a format that isn't supported. |
410 | Gone -- The requested object has been removed from our servers. |
422 | Unprocessable Entity -- Something happened when we tried to save your request. |
429 | Too Many Requests -- You're making too many requests! Slow down! |
500 | Internal Server Error -- We had a problem in our servers. Please try again later. |
503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |
Error Handling
All errors follow the JSend specification. Following are examples of error objects found in the body of error responses (e.g. non-200 status code).
When a client sends an unexpected request:
JSON Example fail response:
{
"status": "fail",
"errors": [
"Document#29f3cb01-744d-4eae-8718-213aec8a1678 not found"
]
}
Field | Type | Description |
---|---|---|
status | String | fail |
errors | Array | Array of error messages |
For server errors:
JSON Example error response:
{
"status": "error",
"message": "500: Internal Server Error"
}
Field | Type | Description |
---|---|---|
status | String | error |
message | String | A descriptive message |